Skip to content

Commit 9ad2857

Browse files
m-kurbanovmiquelraynal
authored andcommitted
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 <[email protected]> Signed-off-by: Miquel Raynal <[email protected]>
1 parent e278b8c commit 9ad2857

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

drivers/mtd/nand/spi/otp.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,115 @@ static int spinand_user_otp_check_bounds(struct spinand_device *spinand,
6666
&spinand->user_otp->layout);
6767
}
6868

69+
static int spinand_otp_rw(struct spinand_device *spinand, loff_t ofs,
70+
size_t len, size_t *retlen, u8 *buf, bool is_write,
71+
const struct spinand_otp_layout *layout)
72+
{
73+
struct nand_page_io_req req = {};
74+
unsigned long long page;
75+
size_t copied = 0;
76+
size_t otp_pagesize = spinand_otp_page_size(spinand);
77+
int ret;
78+
79+
if (!len)
80+
return 0;
81+
82+
ret = spinand_otp_check_bounds(spinand, ofs, len, layout);
83+
if (ret)
84+
return ret;
85+
86+
ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, CFG_OTP_ENABLE);
87+
if (ret)
88+
return ret;
89+
90+
page = ofs;
91+
req.dataoffs = do_div(page, otp_pagesize);
92+
req.pos.page = page + layout->start_page;
93+
req.type = is_write ? NAND_PAGE_WRITE : NAND_PAGE_READ;
94+
req.mode = MTD_OPS_RAW;
95+
req.databuf.in = buf;
96+
97+
while (copied < len) {
98+
req.datalen = min_t(unsigned int,
99+
otp_pagesize - req.dataoffs,
100+
len - copied);
101+
102+
if (is_write)
103+
ret = spinand_write_page(spinand, &req);
104+
else
105+
ret = spinand_read_page(spinand, &req);
106+
107+
if (ret < 0)
108+
break;
109+
110+
req.databuf.in += req.datalen;
111+
req.pos.page++;
112+
req.dataoffs = 0;
113+
copied += req.datalen;
114+
}
115+
116+
*retlen = copied;
117+
118+
if (spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0)) {
119+
dev_warn(&spinand_to_mtd(spinand)->dev,
120+
"Can not disable OTP mode\n");
121+
ret = -EIO;
122+
}
123+
124+
return ret;
125+
}
126+
127+
/**
128+
* spinand_fact_otp_read() - Read from OTP area
129+
* @spinand: the spinand device
130+
* @ofs: the offset to read
131+
* @len: the number of data bytes to read
132+
* @retlen: the pointer to variable to store the number of read bytes
133+
* @buf: the buffer to store the read data
134+
*
135+
* Return: 0 on success, an error code otherwise.
136+
*/
137+
int spinand_fact_otp_read(struct spinand_device *spinand, loff_t ofs,
138+
size_t len, size_t *retlen, u8 *buf)
139+
{
140+
return spinand_otp_rw(spinand, ofs, len, retlen, buf, false,
141+
&spinand->fact_otp->layout);
142+
}
143+
144+
/**
145+
* spinand_user_otp_read() - Read from OTP area
146+
* @spinand: the spinand device
147+
* @ofs: the offset to read
148+
* @len: the number of data bytes to read
149+
* @retlen: the pointer to variable to store the number of read bytes
150+
* @buf: the buffer to store the read data
151+
*
152+
* Return: 0 on success, an error code otherwise.
153+
*/
154+
int spinand_user_otp_read(struct spinand_device *spinand, loff_t ofs,
155+
size_t len, size_t *retlen, u8 *buf)
156+
{
157+
return spinand_otp_rw(spinand, ofs, len, retlen, buf, false,
158+
&spinand->user_otp->layout);
159+
}
160+
161+
/**
162+
* spinand_user_otp_write() - Write to OTP area
163+
* @spinand: the spinand device
164+
* @ofs: the offset to write to
165+
* @len: the number of bytes to write
166+
* @retlen: the pointer to variable to store the number of written bytes
167+
* @buf: the buffer with data to write
168+
*
169+
* Return: 0 on success, an error code otherwise.
170+
*/
171+
int spinand_user_otp_write(struct spinand_device *spinand, loff_t ofs,
172+
size_t len, size_t *retlen, const u8 *buf)
173+
{
174+
return spinand_otp_rw(spinand, ofs, len, retlen, (u8 *)buf, true,
175+
&spinand->user_otp->layout);
176+
}
177+
69178
static int spinand_mtd_otp_info(struct mtd_info *mtd, size_t len,
70179
size_t *retlen, struct otp_info *buf,
71180
bool is_fact)

include/linux/mtd/spinand.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,13 @@ size_t spinand_otp_page_size(struct spinand_device *spinand);
689689
size_t spinand_fact_otp_size(struct spinand_device *spinand);
690690
size_t spinand_user_otp_size(struct spinand_device *spinand);
691691

692+
int spinand_fact_otp_read(struct spinand_device *spinand, loff_t ofs,
693+
size_t len, size_t *retlen, u8 *buf);
694+
int spinand_user_otp_read(struct spinand_device *spinand, loff_t ofs,
695+
size_t len, size_t *retlen, u8 *buf);
696+
int spinand_user_otp_write(struct spinand_device *spinand, loff_t ofs,
697+
size_t len, size_t *retlen, const u8 *buf);
698+
692699
int spinand_set_mtd_otp_ops(struct spinand_device *spinand);
693700

694701
#endif /* __LINUX_MTD_SPINAND_H */

0 commit comments

Comments
 (0)