1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2025, SaluteDevices. All Rights Reserved. 4 * 5 * Author: Martin Kurbanov <mmkurbanov@salutedevices.com> 6 */ 7 8 #include <linux/mtd/mtd.h> 9 #include <linux/mtd/spinand.h> 10 11 /** 12 * spinand_otp_page_size() - Get SPI-NAND OTP page size 13 * @spinand: the spinand device 14 * 15 * Return: the OTP page size. 16 */ 17 size_t spinand_otp_page_size(struct spinand_device *spinand) 18 { 19 struct nand_device *nand = spinand_to_nand(spinand); 20 21 return nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); 22 } 23 24 static size_t spinand_otp_size(struct spinand_device *spinand, 25 const struct spinand_otp_layout *layout) 26 { 27 return layout->npages * spinand_otp_page_size(spinand); 28 } 29 30 /** 31 * spinand_fact_otp_size() - Get SPI-NAND factory OTP area size 32 * @spinand: the spinand device 33 * 34 * Return: the OTP size. 35 */ 36 size_t spinand_fact_otp_size(struct spinand_device *spinand) 37 { 38 return spinand_otp_size(spinand, &spinand->fact_otp->layout); 39 } 40 41 /** 42 * spinand_user_otp_size() - Get SPI-NAND user OTP area size 43 * @spinand: the spinand device 44 * 45 * Return: the OTP size. 46 */ 47 size_t spinand_user_otp_size(struct spinand_device *spinand) 48 { 49 return spinand_otp_size(spinand, &spinand->user_otp->layout); 50 } 51 52 static int spinand_otp_check_bounds(struct spinand_device *spinand, loff_t ofs, 53 size_t len, 54 const struct spinand_otp_layout *layout) 55 { 56 if (ofs < 0 || ofs + len > spinand_otp_size(spinand, layout)) 57 return -EINVAL; 58 59 return 0; 60 } 61 62 static int spinand_user_otp_check_bounds(struct spinand_device *spinand, 63 loff_t ofs, size_t len) 64 { 65 return spinand_otp_check_bounds(spinand, ofs, len, 66 &spinand->user_otp->layout); 67 } 68 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 178 static int spinand_mtd_otp_info(struct mtd_info *mtd, size_t len, 179 size_t *retlen, struct otp_info *buf, 180 bool is_fact) 181 { 182 struct spinand_device *spinand = mtd_to_spinand(mtd); 183 int ret; 184 185 *retlen = 0; 186 187 mutex_lock(&spinand->lock); 188 189 if (is_fact) 190 ret = spinand->fact_otp->ops->info(spinand, len, buf, retlen); 191 else 192 ret = spinand->user_otp->ops->info(spinand, len, buf, retlen); 193 194 mutex_unlock(&spinand->lock); 195 196 return ret; 197 } 198 199 static int spinand_mtd_fact_otp_info(struct mtd_info *mtd, size_t len, 200 size_t *retlen, struct otp_info *buf) 201 { 202 return spinand_mtd_otp_info(mtd, len, retlen, buf, true); 203 } 204 205 static int spinand_mtd_user_otp_info(struct mtd_info *mtd, size_t len, 206 size_t *retlen, struct otp_info *buf) 207 { 208 return spinand_mtd_otp_info(mtd, len, retlen, buf, false); 209 } 210 211 static int spinand_mtd_otp_read(struct mtd_info *mtd, loff_t ofs, size_t len, 212 size_t *retlen, u8 *buf, bool is_fact) 213 { 214 struct spinand_device *spinand = mtd_to_spinand(mtd); 215 int ret; 216 217 *retlen = 0; 218 219 if (!len) 220 return 0; 221 222 ret = spinand_otp_check_bounds(spinand, ofs, len, 223 is_fact ? &spinand->fact_otp->layout : 224 &spinand->user_otp->layout); 225 if (ret) 226 return ret; 227 228 mutex_lock(&spinand->lock); 229 230 if (is_fact) 231 ret = spinand->fact_otp->ops->read(spinand, ofs, len, retlen, 232 buf); 233 else 234 ret = spinand->user_otp->ops->read(spinand, ofs, len, retlen, 235 buf); 236 237 mutex_unlock(&spinand->lock); 238 239 return ret; 240 } 241 242 static int spinand_mtd_fact_otp_read(struct mtd_info *mtd, loff_t ofs, 243 size_t len, size_t *retlen, u8 *buf) 244 { 245 return spinand_mtd_otp_read(mtd, ofs, len, retlen, buf, true); 246 } 247 248 static int spinand_mtd_user_otp_read(struct mtd_info *mtd, loff_t ofs, 249 size_t len, size_t *retlen, u8 *buf) 250 { 251 return spinand_mtd_otp_read(mtd, ofs, len, retlen, buf, false); 252 } 253 254 static int spinand_mtd_user_otp_write(struct mtd_info *mtd, loff_t ofs, 255 size_t len, size_t *retlen, const u8 *buf) 256 { 257 struct spinand_device *spinand = mtd_to_spinand(mtd); 258 const struct spinand_user_otp_ops *ops = spinand->user_otp->ops; 259 int ret; 260 261 *retlen = 0; 262 263 if (!len) 264 return 0; 265 266 ret = spinand_user_otp_check_bounds(spinand, ofs, len); 267 if (ret) 268 return ret; 269 270 mutex_lock(&spinand->lock); 271 ret = ops->write(spinand, ofs, len, retlen, buf); 272 mutex_unlock(&spinand->lock); 273 274 return ret; 275 } 276 277 static int spinand_mtd_user_otp_erase(struct mtd_info *mtd, loff_t ofs, 278 size_t len) 279 { 280 struct spinand_device *spinand = mtd_to_spinand(mtd); 281 const struct spinand_user_otp_ops *ops = spinand->user_otp->ops; 282 int ret; 283 284 if (!len) 285 return 0; 286 287 ret = spinand_user_otp_check_bounds(spinand, ofs, len); 288 if (ret) 289 return ret; 290 291 mutex_lock(&spinand->lock); 292 ret = ops->erase(spinand, ofs, len); 293 mutex_unlock(&spinand->lock); 294 295 return ret; 296 } 297 298 static int spinand_mtd_user_otp_lock(struct mtd_info *mtd, loff_t ofs, 299 size_t len) 300 { 301 struct spinand_device *spinand = mtd_to_spinand(mtd); 302 const struct spinand_user_otp_ops *ops = spinand->user_otp->ops; 303 int ret; 304 305 if (!len) 306 return 0; 307 308 ret = spinand_user_otp_check_bounds(spinand, ofs, len); 309 if (ret) 310 return ret; 311 312 mutex_lock(&spinand->lock); 313 ret = ops->lock(spinand, ofs, len); 314 mutex_unlock(&spinand->lock); 315 316 return ret; 317 } 318 319 /** 320 * spinand_set_mtd_otp_ops() - Setup OTP methods 321 * @spinand: the spinand device 322 * 323 * Setup OTP methods. 324 * 325 * Return: 0 on success, a negative error code otherwise. 326 */ 327 int spinand_set_mtd_otp_ops(struct spinand_device *spinand) 328 { 329 struct mtd_info *mtd = spinand_to_mtd(spinand); 330 const struct spinand_fact_otp_ops *fact_ops = spinand->fact_otp->ops; 331 const struct spinand_user_otp_ops *user_ops = spinand->user_otp->ops; 332 333 if (!user_ops && !fact_ops) 334 return -EINVAL; 335 336 if (user_ops) { 337 if (user_ops->info) 338 mtd->_get_user_prot_info = spinand_mtd_user_otp_info; 339 340 if (user_ops->read) 341 mtd->_read_user_prot_reg = spinand_mtd_user_otp_read; 342 343 if (user_ops->write) 344 mtd->_write_user_prot_reg = spinand_mtd_user_otp_write; 345 346 if (user_ops->lock) 347 mtd->_lock_user_prot_reg = spinand_mtd_user_otp_lock; 348 349 if (user_ops->erase) 350 mtd->_erase_user_prot_reg = spinand_mtd_user_otp_erase; 351 } 352 353 if (fact_ops) { 354 if (fact_ops->info) 355 mtd->_get_fact_prot_info = spinand_mtd_fact_otp_info; 356 357 if (fact_ops->read) 358 mtd->_read_fact_prot_reg = spinand_mtd_fact_otp_read; 359 } 360 361 return 0; 362 } 363