mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
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 <mmkurbanov@salutedevices.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
parent
e278b8c73b
commit
9ad2857c82
|
|
@ -66,6 +66,115 @@ static int spinand_user_otp_check_bounds(struct spinand_device *spinand,
|
|||
&spinand->user_otp->layout);
|
||||
}
|
||||
|
||||
static int spinand_otp_rw(struct spinand_device *spinand, loff_t ofs,
|
||||
size_t len, size_t *retlen, u8 *buf, bool is_write,
|
||||
const struct spinand_otp_layout *layout)
|
||||
{
|
||||
struct nand_page_io_req req = {};
|
||||
unsigned long long page;
|
||||
size_t copied = 0;
|
||||
size_t otp_pagesize = spinand_otp_page_size(spinand);
|
||||
int ret;
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
ret = spinand_otp_check_bounds(spinand, ofs, len, layout);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, CFG_OTP_ENABLE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
page = ofs;
|
||||
req.dataoffs = do_div(page, otp_pagesize);
|
||||
req.pos.page = page + layout->start_page;
|
||||
req.type = is_write ? NAND_PAGE_WRITE : NAND_PAGE_READ;
|
||||
req.mode = MTD_OPS_RAW;
|
||||
req.databuf.in = buf;
|
||||
|
||||
while (copied < len) {
|
||||
req.datalen = min_t(unsigned int,
|
||||
otp_pagesize - req.dataoffs,
|
||||
len - copied);
|
||||
|
||||
if (is_write)
|
||||
ret = spinand_write_page(spinand, &req);
|
||||
else
|
||||
ret = spinand_read_page(spinand, &req);
|
||||
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
req.databuf.in += req.datalen;
|
||||
req.pos.page++;
|
||||
req.dataoffs = 0;
|
||||
copied += req.datalen;
|
||||
}
|
||||
|
||||
*retlen = copied;
|
||||
|
||||
if (spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0)) {
|
||||
dev_warn(&spinand_to_mtd(spinand)->dev,
|
||||
"Can not disable OTP mode\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* spinand_fact_otp_read() - Read from OTP area
|
||||
* @spinand: the spinand device
|
||||
* @ofs: the offset to read
|
||||
* @len: the number of data bytes to read
|
||||
* @retlen: the pointer to variable to store the number of read bytes
|
||||
* @buf: the buffer to store the read data
|
||||
*
|
||||
* Return: 0 on success, an error code otherwise.
|
||||
*/
|
||||
int spinand_fact_otp_read(struct spinand_device *spinand, loff_t ofs,
|
||||
size_t len, size_t *retlen, u8 *buf)
|
||||
{
|
||||
return spinand_otp_rw(spinand, ofs, len, retlen, buf, false,
|
||||
&spinand->fact_otp->layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* spinand_user_otp_read() - Read from OTP area
|
||||
* @spinand: the spinand device
|
||||
* @ofs: the offset to read
|
||||
* @len: the number of data bytes to read
|
||||
* @retlen: the pointer to variable to store the number of read bytes
|
||||
* @buf: the buffer to store the read data
|
||||
*
|
||||
* Return: 0 on success, an error code otherwise.
|
||||
*/
|
||||
int spinand_user_otp_read(struct spinand_device *spinand, loff_t ofs,
|
||||
size_t len, size_t *retlen, u8 *buf)
|
||||
{
|
||||
return spinand_otp_rw(spinand, ofs, len, retlen, buf, false,
|
||||
&spinand->user_otp->layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* spinand_user_otp_write() - Write to OTP area
|
||||
* @spinand: the spinand device
|
||||
* @ofs: the offset to write to
|
||||
* @len: the number of bytes to write
|
||||
* @retlen: the pointer to variable to store the number of written bytes
|
||||
* @buf: the buffer with data to write
|
||||
*
|
||||
* Return: 0 on success, an error code otherwise.
|
||||
*/
|
||||
int spinand_user_otp_write(struct spinand_device *spinand, loff_t ofs,
|
||||
size_t len, size_t *retlen, const u8 *buf)
|
||||
{
|
||||
return spinand_otp_rw(spinand, ofs, len, retlen, (u8 *)buf, true,
|
||||
&spinand->user_otp->layout);
|
||||
}
|
||||
|
||||
static int spinand_mtd_otp_info(struct mtd_info *mtd, size_t len,
|
||||
size_t *retlen, struct otp_info *buf,
|
||||
bool is_fact)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user