From 07d0aa9393abc8fd64d0a174edfb68c5808187e4 Mon Sep 17 00:00:00 2001 From: Martin Kurbanov Date: Mon, 10 Feb 2025 17:34:13 +0300 Subject: mtd: spinand: make spinand_{read,write}_page global Change these functions from static to global so that to use them later in OTP operations. Since reading OTP pages is no different from reading pages from the main area. Signed-off-by: Martin Kurbanov Signed-off-by: Miquel Raynal --- include/linux/mtd/spinand.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 0da8a1c7740e..34ddd2441fc9 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -588,4 +588,10 @@ int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val); int spinand_write_reg_op(struct spinand_device *spinand, u8 reg, u8 val); int spinand_select_target(struct spinand_device *spinand, unsigned int target); +int spinand_read_page(struct spinand_device *spinand, + const struct nand_page_io_req *req); + +int spinand_write_page(struct spinand_device *spinand, + const struct nand_page_io_req *req); + #endif /* __LINUX_MTD_SPINAND_H */ -- cgit v1.2.3 From c06b1f753bea40a282f29a9383fcf36b12323108 Mon Sep 17 00:00:00 2001 From: Martin Kurbanov Date: Mon, 10 Feb 2025 17:34:14 +0300 Subject: mtd: spinand: add OTP support The MTD subsystem already supports accessing two OTP areas: user and factory. User areas can be written by the user. This patch provides the SPINAND_FACT_OTP_INFO and SPINAND_USER_OTP_INFO macros to add parameters to spinand_info. To implement OTP operations, the client (flash driver) is provided with callbacks for user area: .read(), .write(), .info(), .lock(), .erase(); and for factory area: .read(), .info(); Signed-off-by: Martin Kurbanov Signed-off-by: Miquel Raynal --- include/linux/mtd/spinand.h | 93 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 34ddd2441fc9..f4c965ae2f65 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -374,6 +374,67 @@ struct spinand_ondie_ecc_conf { u8 status; }; +/** + * struct spinand_otp_layout - structure to describe the SPI NAND OTP area + * @npages: number of pages in the OTP + * @start_page: start page of the user/factory OTP area. + */ +struct spinand_otp_layout { + unsigned int npages; + unsigned int start_page; +}; + +/** + * struct spinand_fact_otp_ops - SPI NAND OTP methods for factory area + * @info: get the OTP area information + * @read: read from the SPI NAND OTP area + */ +struct spinand_fact_otp_ops { + int (*info)(struct spinand_device *spinand, size_t len, + struct otp_info *buf, size_t *retlen); + int (*read)(struct spinand_device *spinand, loff_t from, size_t len, + size_t *retlen, u8 *buf); +}; + +/** + * struct spinand_user_otp_ops - SPI NAND OTP methods for user area + * @info: get the OTP area information + * @lock: lock an OTP region + * @erase: erase an OTP region + * @read: read from the SPI NAND OTP area + * @write: write to the SPI NAND OTP area + */ +struct spinand_user_otp_ops { + int (*info)(struct spinand_device *spinand, size_t len, + struct otp_info *buf, size_t *retlen); + int (*lock)(struct spinand_device *spinand, loff_t from, size_t len); + int (*erase)(struct spinand_device *spinand, loff_t from, size_t len); + int (*read)(struct spinand_device *spinand, loff_t from, size_t len, + size_t *retlen, u8 *buf); + int (*write)(struct spinand_device *spinand, loff_t from, size_t len, + size_t *retlen, const u8 *buf); +}; + +/** + * struct spinand_fact_otp - SPI NAND OTP grouping structure for factory area + * @layout: OTP region layout + * @ops: OTP access ops + */ +struct spinand_fact_otp { + const struct spinand_otp_layout layout; + const struct spinand_fact_otp_ops *ops; +}; + +/** + * struct spinand_user_otp - SPI NAND OTP grouping structure for user area + * @layout: OTP region layout + * @ops: OTP access ops + */ +struct spinand_user_otp { + const struct spinand_otp_layout layout; + const struct spinand_user_otp_ops *ops; +}; + /** * struct spinand_info - Structure used to describe SPI NAND chips * @model: model name @@ -389,6 +450,8 @@ struct spinand_ondie_ecc_conf { * @select_target: function used to select a target/die. Required only for * multi-die chips * @set_cont_read: enable/disable continuous cached reads + * @fact_otp: SPI NAND factory OTP info. + * @user_otp: SPI NAND user OTP info. * * Each SPI NAND manufacturer driver should have a spinand_info table * describing all the chips supported by the driver. @@ -409,6 +472,8 @@ struct spinand_info { unsigned int target); int (*set_cont_read)(struct spinand_device *spinand, bool enable); + struct spinand_fact_otp fact_otp; + struct spinand_user_otp user_otp; }; #define SPINAND_ID(__method, ...) \ @@ -437,6 +502,24 @@ struct spinand_info { #define SPINAND_CONT_READ(__set_cont_read) \ .set_cont_read = __set_cont_read, +#define SPINAND_FACT_OTP_INFO(__npages, __start_page, __ops) \ + .fact_otp = { \ + .layout = { \ + .npages = __npages, \ + .start_page = __start_page, \ + }, \ + .ops = __ops, \ + } + +#define SPINAND_USER_OTP_INFO(__npages, __start_page, __ops) \ + .user_otp = { \ + .layout = { \ + .npages = __npages, \ + .start_page = __start_page, \ + }, \ + .ops = __ops, \ + } + #define SPINAND_INFO(__model, __id, __memorg, __eccreq, __op_variants, \ __flags, ...) \ { \ @@ -487,6 +570,8 @@ struct spinand_dirmap { * actually relevant to enable this feature. * @set_cont_read: Enable/disable the continuous read feature * @priv: manufacturer private data + * @fact_otp: SPI NAND factory OTP info. + * @user_otp: SPI NAND user OTP info. */ struct spinand_device { struct nand_device base; @@ -519,6 +604,9 @@ struct spinand_device { bool cont_read_possible; int (*set_cont_read)(struct spinand_device *spinand, bool enable); + + const struct spinand_fact_otp *fact_otp; + const struct spinand_user_otp *user_otp; }; /** @@ -594,4 +682,9 @@ int spinand_read_page(struct spinand_device *spinand, int spinand_write_page(struct spinand_device *spinand, const struct nand_page_io_req *req); +size_t spinand_fact_otp_size(struct spinand_device *spinand); +size_t spinand_user_otp_size(struct spinand_device *spinand); + +int spinand_set_mtd_otp_ops(struct spinand_device *spinand); + #endif /* __LINUX_MTD_SPINAND_H */ -- cgit v1.2.3 From e278b8c73b0526f8e3ee22f4827c8fe07c2109ba Mon Sep 17 00:00:00 2001 From: Martin Kurbanov Date: Mon, 10 Feb 2025 17:34:15 +0300 Subject: mtd: spinand: make spinand_{wait,otp_page_size} global Change the functions spinand_wait() and spinand_otp_page_size() from static to global so that SPI NAND flash drivers don't duplicate it. Signed-off-by: Martin Kurbanov Signed-off-by: Miquel Raynal --- include/linux/mtd/spinand.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index f4c965ae2f65..597d28339d15 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -676,12 +676,16 @@ int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val); int spinand_write_reg_op(struct spinand_device *spinand, u8 reg, u8 val); int spinand_select_target(struct spinand_device *spinand, unsigned int target); +int spinand_wait(struct spinand_device *spinand, unsigned long initial_delay_us, + unsigned long poll_delay_us, u8 *s); + int spinand_read_page(struct spinand_device *spinand, const struct nand_page_io_req *req); int spinand_write_page(struct spinand_device *spinand, const struct nand_page_io_req *req); +size_t spinand_otp_page_size(struct spinand_device *spinand); size_t spinand_fact_otp_size(struct spinand_device *spinand); size_t spinand_user_otp_size(struct spinand_device *spinand); -- cgit v1.2.3 From 9ad2857c82d56017402256fd3e2ed401cc7f6fb9 Mon Sep 17 00:00:00 2001 From: Martin Kurbanov Date: Mon, 10 Feb 2025 17:34:16 +0300 Subject: mtd: spinand: otp: add helpers functions The global functions spinand_otp_read() and spinand_otp_write() have been introduced. Since most SPI-NAND flashes read/write OTP in the same way, let's define global functions to avoid code duplication. Signed-off-by: Martin Kurbanov Signed-off-by: Miquel Raynal --- include/linux/mtd/spinand.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 597d28339d15..73424405232a 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -689,6 +689,13 @@ size_t spinand_otp_page_size(struct spinand_device *spinand); size_t spinand_fact_otp_size(struct spinand_device *spinand); size_t spinand_user_otp_size(struct spinand_device *spinand); +int spinand_fact_otp_read(struct spinand_device *spinand, loff_t ofs, + size_t len, size_t *retlen, u8 *buf); +int spinand_user_otp_read(struct spinand_device *spinand, loff_t ofs, + size_t len, size_t *retlen, u8 *buf); +int spinand_user_otp_write(struct spinand_device *spinand, loff_t ofs, + size_t len, size_t *retlen, const u8 *buf); + int spinand_set_mtd_otp_ops(struct spinand_device *spinand); #endif /* __LINUX_MTD_SPINAND_H */ -- cgit v1.2.3 From 1db50b96b059ca8e5548cb3e0e38a888b325f96b Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 9 Feb 2025 15:54:32 +0100 Subject: mtd: rawnand: qcom: finish converting register to FIELD_PREP With some research in some obscure old QSDK, it was possible to find the MASK of the last register there were still set with raw shift and convert them to FIELD_PREP API. This is only a cleanup and modernize the code a bit and doesn't make any behaviour change. Signed-off-by: Christian Marangi Signed-off-by: Miquel Raynal --- include/linux/mtd/nand-qpic-common.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/nand-qpic-common.h b/include/linux/mtd/nand-qpic-common.h index 4d9b736ff8b7..35e7ee0f7809 100644 --- a/include/linux/mtd/nand-qpic-common.h +++ b/include/linux/mtd/nand-qpic-common.h @@ -108,7 +108,7 @@ #define ECC_FORCE_CLK_OPEN BIT(30) /* NAND_DEV_CMD1 bits */ -#define READ_ADDR 0 +#define READ_ADDR_MASK GENMASK(7, 0) /* NAND_DEV_CMD_VLD bits */ #define READ_START_VLD BIT(0) @@ -119,6 +119,7 @@ /* NAND_EBI2_ECC_BUF_CFG bits */ #define NUM_STEPS 0 +#define NUM_STEPS_MASK GENMASK(9, 0) /* NAND_ERASED_CW_DETECT_CFG bits */ #define ERASED_CW_ECC_MASK 1 @@ -139,8 +140,11 @@ /* NAND_READ_LOCATION_n bits */ #define READ_LOCATION_OFFSET 0 +#define READ_LOCATION_OFFSET_MASK GENMASK(9, 0) #define READ_LOCATION_SIZE 16 +#define READ_LOCATION_SIZE_MASK GENMASK(25, 16) #define READ_LOCATION_LAST 31 +#define READ_LOCATION_LAST_MASK BIT(31) /* Version Mask */ #define NAND_VERSION_MAJOR_MASK 0xf0000000 -- cgit v1.2.3 From f2cb43c98010181b532ff36643731dc2442b9b7d Mon Sep 17 00:00:00 2001 From: Cheng Ming Lin Date: Mon, 24 Feb 2025 15:03:48 +0800 Subject: mtd: spinand: Add read retry support When the host ECC fails to correct the data error of NAND device, there's a special read for data recovery method which can be setup by the host for the next read. There are several retry levels that can be attempted until the lost data is recovered or definitely assumed lost. Signed-off-by: Cheng Ming Lin Signed-off-by: Miquel Raynal --- include/linux/mtd/spinand.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 73424405232a..5837a09ab9d8 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -452,6 +452,8 @@ struct spinand_user_otp { * @set_cont_read: enable/disable continuous cached reads * @fact_otp: SPI NAND factory OTP info. * @user_otp: SPI NAND user OTP info. + * @read_retries: the number of read retry modes supported + * @set_read_retry: enable/disable read retry for data recovery * * Each SPI NAND manufacturer driver should have a spinand_info table * describing all the chips supported by the driver. @@ -474,6 +476,9 @@ struct spinand_info { bool enable); struct spinand_fact_otp fact_otp; struct spinand_user_otp user_otp; + unsigned int read_retries; + int (*set_read_retry)(struct spinand_device *spinand, + unsigned int read_retry); }; #define SPINAND_ID(__method, ...) \ @@ -520,6 +525,10 @@ struct spinand_info { .ops = __ops, \ } +#define SPINAND_READ_RETRY(__read_retries, __set_read_retry) \ + .read_retries = __read_retries, \ + .set_read_retry = __set_read_retry, + #define SPINAND_INFO(__model, __id, __memorg, __eccreq, __op_variants, \ __flags, ...) \ { \ @@ -572,6 +581,8 @@ struct spinand_dirmap { * @priv: manufacturer private data * @fact_otp: SPI NAND factory OTP info. * @user_otp: SPI NAND user OTP info. + * @read_retries: the number of read retry modes supported + * @set_read_retry: Enable/disable the read retry feature */ struct spinand_device { struct nand_device base; @@ -607,6 +618,10 @@ struct spinand_device { const struct spinand_fact_otp *fact_otp; const struct spinand_user_otp *user_otp; + + unsigned int read_retries; + int (*set_read_retry)(struct spinand_device *spinand, + unsigned int retry_mode); }; /** -- cgit v1.2.3 From b28f47ac3ddd072cce0e447ace89e2b4d6932c66 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 4 Mar 2025 12:05:39 +0100 Subject: mtd: spinand: Improve spinand_info macros style Let's assume all these macros should not have a trailing comma, this way the caller can use a more formal and usual C writing style, as reflected in the Macronix driver. Acked-by: Pratyush Yadav Signed-off-by: Miquel Raynal --- include/linux/mtd/spinand.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 5837a09ab9d8..1e748958dad4 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -502,10 +502,10 @@ struct spinand_info { } #define SPINAND_SELECT_TARGET(__func) \ - .select_target = __func, + .select_target = __func #define SPINAND_CONT_READ(__set_cont_read) \ - .set_cont_read = __set_cont_read, + .set_cont_read = __set_cont_read #define SPINAND_FACT_OTP_INFO(__npages, __start_page, __ops) \ .fact_otp = { \ @@ -526,8 +526,8 @@ struct spinand_info { } #define SPINAND_READ_RETRY(__read_retries, __set_read_retry) \ - .read_retries = __read_retries, \ - .set_read_retry = __set_read_retry, + .read_retries = __read_retries, \ + .set_read_retry = __set_read_retry #define SPINAND_INFO(__model, __id, __memorg, __eccreq, __op_variants, \ __flags, ...) \ -- cgit v1.2.3 From ca8cbbb2be8f906d9602a6e4324f8adf279e9cc2 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 5 Mar 2025 20:49:55 +0100 Subject: mtd: nand: Fix a kdoc comment The max_bad_eraseblocks_per_lun member of nand_device obviously describes a number of *maximum* number of bad eraseblocks per LUN. Fix this obvious typo. Fixes: 377e517b5fa5 ("mtd: nand: Add max_bad_eraseblocks_per_lun info to memorg") Cc: # fix kdoc comment Reviewed-by: Tudor Ambarus Signed-off-by: Miquel Raynal --- include/linux/mtd/nand.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/mtd') diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 0e2f228e8b4a..07486168d104 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -21,7 +21,7 @@ struct nand_device; * @oobsize: OOB area size * @pages_per_eraseblock: number of pages per eraseblock * @eraseblocks_per_lun: number of eraseblocks per LUN (Logical Unit Number) - * @max_bad_eraseblocks_per_lun: maximum number of eraseblocks per LUN + * @max_bad_eraseblocks_per_lun: maximum number of bad eraseblocks per LUN * @planes_per_lun: number of planes per LUN * @luns_per_target: number of LUN per target (target is a synonym for die) * @ntargets: total number of targets exposed by the NAND device -- cgit v1.2.3