diff options
| author | Martin Kurbanov <mmkurbanov@salutedevices.com> | 2025-02-10 17:34:14 +0300 |
|---|---|---|
| committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2025-02-10 15:52:59 +0100 |
| commit | c06b1f753bea40a282f29a9383fcf36b12323108 (patch) | |
| tree | ea16a488f3039f7256e909397b85cdbd4fcef2be /include/linux/mtd | |
| parent | 07d0aa9393abc8fd64d0a174edfb68c5808187e4 (diff) | |
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 <mmkurbanov@salutedevices.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Diffstat (limited to 'include/linux/mtd')
| -rw-r--r-- | include/linux/mtd/spinand.h | 93 |
1 files changed, 93 insertions, 0 deletions
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 @@ -375,6 +375,67 @@ struct spinand_ondie_ecc_conf { }; /** + * 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 * @devid: device ID @@ -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 */ |
