1069089acSMichael Walle // SPDX-License-Identifier: GPL-2.0 2069089acSMichael Walle /* 3069089acSMichael Walle * OTP support for SPI NOR flashes 4069089acSMichael Walle * 5069089acSMichael Walle * Copyright (C) 2021 Michael Walle <michael@walle.cc> 6069089acSMichael Walle */ 7069089acSMichael Walle 8069089acSMichael Walle #include <linux/log2.h> 9069089acSMichael Walle #include <linux/mtd/mtd.h> 10069089acSMichael Walle #include <linux/mtd/spi-nor.h> 11069089acSMichael Walle 12069089acSMichael Walle #include "core.h" 13069089acSMichael Walle 14069089acSMichael Walle #define spi_nor_otp_region_len(nor) ((nor)->params->otp.org->len) 15069089acSMichael Walle #define spi_nor_otp_n_regions(nor) ((nor)->params->otp.org->n_regions) 16069089acSMichael Walle 17cad3193fSMichael Walle /** 18d5b813e4SMichael Walle * spi_nor_otp_read_secr() - read security register 19cad3193fSMichael Walle * @nor: pointer to 'struct spi_nor' 20a6e2cd4dSMichael Walle * @addr: offset to read from 21cad3193fSMichael Walle * @len: number of bytes to read 22cad3193fSMichael Walle * @buf: pointer to dst buffer 23cad3193fSMichael Walle * 24d5b813e4SMichael Walle * Read a security register by using the SPINOR_OP_RSECR commands. 25d5b813e4SMichael Walle * 26d5b813e4SMichael Walle * In Winbond/GigaDevice datasheets the term "security register" stands for 27d5b813e4SMichael Walle * an one-time-programmable memory area, consisting of multiple bytes (usually 28d5b813e4SMichael Walle * 256). Thus one "security register" maps to one OTP region. 29d5b813e4SMichael Walle * 30d5b813e4SMichael Walle * This method is used on GigaDevice and Winbond flashes. 31d5b813e4SMichael Walle * 32d5b813e4SMichael Walle * Please note, the read must not span multiple registers. 33cad3193fSMichael Walle * 34cad3193fSMichael Walle * Return: number of bytes read successfully, -errno otherwise 35cad3193fSMichael Walle */ 36cad3193fSMichael Walle int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t len, u8 *buf) 37cad3193fSMichael Walle { 38cad3193fSMichael Walle u8 addr_width, read_opcode, read_dummy; 39cad3193fSMichael Walle struct spi_mem_dirmap_desc *rdesc; 40cad3193fSMichael Walle enum spi_nor_protocol read_proto; 41cad3193fSMichael Walle int ret; 42cad3193fSMichael Walle 43cad3193fSMichael Walle read_opcode = nor->read_opcode; 44cad3193fSMichael Walle addr_width = nor->addr_width; 45cad3193fSMichael Walle read_dummy = nor->read_dummy; 46cad3193fSMichael Walle read_proto = nor->read_proto; 47cad3193fSMichael Walle rdesc = nor->dirmap.rdesc; 48cad3193fSMichael Walle 49cad3193fSMichael Walle nor->read_opcode = SPINOR_OP_RSECR; 50cad3193fSMichael Walle nor->read_dummy = 8; 51cad3193fSMichael Walle nor->read_proto = SNOR_PROTO_1_1_1; 52cad3193fSMichael Walle nor->dirmap.rdesc = NULL; 53cad3193fSMichael Walle 54cad3193fSMichael Walle ret = spi_nor_read_data(nor, addr, len, buf); 55cad3193fSMichael Walle 56cad3193fSMichael Walle nor->read_opcode = read_opcode; 57cad3193fSMichael Walle nor->addr_width = addr_width; 58cad3193fSMichael Walle nor->read_dummy = read_dummy; 59cad3193fSMichael Walle nor->read_proto = read_proto; 60cad3193fSMichael Walle nor->dirmap.rdesc = rdesc; 61cad3193fSMichael Walle 62cad3193fSMichael Walle return ret; 63cad3193fSMichael Walle } 64cad3193fSMichael Walle 65cad3193fSMichael Walle /** 66d5b813e4SMichael Walle * spi_nor_otp_write_secr() - write security register 67cad3193fSMichael Walle * @nor: pointer to 'struct spi_nor' 68a6e2cd4dSMichael Walle * @addr: offset to write to 69cad3193fSMichael Walle * @len: number of bytes to write 70cad3193fSMichael Walle * @buf: pointer to src buffer 71cad3193fSMichael Walle * 72d5b813e4SMichael Walle * Write a security register by using the SPINOR_OP_PSECR commands. 73cad3193fSMichael Walle * 74d5b813e4SMichael Walle * For more information on the term "security register", see the documentation 75d5b813e4SMichael Walle * of spi_nor_otp_read_secr(). 76d5b813e4SMichael Walle * 77d5b813e4SMichael Walle * This method is used on GigaDevice and Winbond flashes. 78d5b813e4SMichael Walle * 79d5b813e4SMichael Walle * Please note, the write must not span multiple registers. 80cad3193fSMichael Walle * 81cad3193fSMichael Walle * Return: number of bytes written successfully, -errno otherwise 82cad3193fSMichael Walle */ 831df1fc8cSTudor Ambarus int spi_nor_otp_write_secr(struct spi_nor *nor, loff_t addr, size_t len, 841df1fc8cSTudor Ambarus const u8 *buf) 85cad3193fSMichael Walle { 86cad3193fSMichael Walle enum spi_nor_protocol write_proto; 87cad3193fSMichael Walle struct spi_mem_dirmap_desc *wdesc; 88cad3193fSMichael Walle u8 addr_width, program_opcode; 89cad3193fSMichael Walle int ret, written; 90cad3193fSMichael Walle 91cad3193fSMichael Walle program_opcode = nor->program_opcode; 92cad3193fSMichael Walle addr_width = nor->addr_width; 93cad3193fSMichael Walle write_proto = nor->write_proto; 94cad3193fSMichael Walle wdesc = nor->dirmap.wdesc; 95cad3193fSMichael Walle 96cad3193fSMichael Walle nor->program_opcode = SPINOR_OP_PSECR; 97cad3193fSMichael Walle nor->write_proto = SNOR_PROTO_1_1_1; 98cad3193fSMichael Walle nor->dirmap.wdesc = NULL; 99cad3193fSMichael Walle 100cad3193fSMichael Walle /* 101cad3193fSMichael Walle * We only support a write to one single page. For now all winbond 102d5b813e4SMichael Walle * flashes only have one page per security register. 103cad3193fSMichael Walle */ 104cad3193fSMichael Walle ret = spi_nor_write_enable(nor); 105cad3193fSMichael Walle if (ret) 106cad3193fSMichael Walle goto out; 107cad3193fSMichael Walle 108cad3193fSMichael Walle written = spi_nor_write_data(nor, addr, len, buf); 109cad3193fSMichael Walle if (written < 0) 110cad3193fSMichael Walle goto out; 111cad3193fSMichael Walle 112cad3193fSMichael Walle ret = spi_nor_wait_till_ready(nor); 113cad3193fSMichael Walle 114cad3193fSMichael Walle out: 115cad3193fSMichael Walle nor->program_opcode = program_opcode; 116cad3193fSMichael Walle nor->addr_width = addr_width; 117cad3193fSMichael Walle nor->write_proto = write_proto; 118cad3193fSMichael Walle nor->dirmap.wdesc = wdesc; 119cad3193fSMichael Walle 120cad3193fSMichael Walle return ret ?: written; 121cad3193fSMichael Walle } 122cad3193fSMichael Walle 123*c6ec3e1eSMichael Walle /** 124*c6ec3e1eSMichael Walle * spi_nor_otp_erase_secr() - erase a security register 125*c6ec3e1eSMichael Walle * @nor: pointer to 'struct spi_nor' 126*c6ec3e1eSMichael Walle * @addr: offset of the security register to be erased 127*c6ec3e1eSMichael Walle * 128*c6ec3e1eSMichael Walle * Erase a security register by using the SPINOR_OP_ESECR command. 129*c6ec3e1eSMichael Walle * 130*c6ec3e1eSMichael Walle * For more information on the term "security register", see the documentation 131*c6ec3e1eSMichael Walle * of spi_nor_otp_read_secr(). 132*c6ec3e1eSMichael Walle * 133*c6ec3e1eSMichael Walle * This method is used on GigaDevice and Winbond flashes. 134*c6ec3e1eSMichael Walle * 135*c6ec3e1eSMichael Walle * Return: 0 on success, -errno otherwise 136*c6ec3e1eSMichael Walle */ 137*c6ec3e1eSMichael Walle int spi_nor_otp_erase_secr(struct spi_nor *nor, loff_t addr) 138*c6ec3e1eSMichael Walle { 139*c6ec3e1eSMichael Walle u8 erase_opcode = nor->erase_opcode; 140*c6ec3e1eSMichael Walle int ret; 141*c6ec3e1eSMichael Walle 142*c6ec3e1eSMichael Walle ret = spi_nor_write_enable(nor); 143*c6ec3e1eSMichael Walle if (ret) 144*c6ec3e1eSMichael Walle return ret; 145*c6ec3e1eSMichael Walle 146*c6ec3e1eSMichael Walle nor->erase_opcode = SPINOR_OP_ESECR; 147*c6ec3e1eSMichael Walle ret = spi_nor_erase_sector(nor, addr); 148*c6ec3e1eSMichael Walle nor->erase_opcode = erase_opcode; 149*c6ec3e1eSMichael Walle if (ret) 150*c6ec3e1eSMichael Walle return ret; 151*c6ec3e1eSMichael Walle 152*c6ec3e1eSMichael Walle return spi_nor_wait_till_ready(nor); 153*c6ec3e1eSMichael Walle } 154*c6ec3e1eSMichael Walle 155cad3193fSMichael Walle static int spi_nor_otp_lock_bit_cr(unsigned int region) 156cad3193fSMichael Walle { 157cad3193fSMichael Walle static const int lock_bits[] = { SR2_LB1, SR2_LB2, SR2_LB3 }; 158cad3193fSMichael Walle 159cad3193fSMichael Walle if (region >= ARRAY_SIZE(lock_bits)) 160cad3193fSMichael Walle return -EINVAL; 161cad3193fSMichael Walle 162cad3193fSMichael Walle return lock_bits[region]; 163cad3193fSMichael Walle } 164cad3193fSMichael Walle 165cad3193fSMichael Walle /** 166cad3193fSMichael Walle * spi_nor_otp_lock_sr2() - lock the OTP region 167cad3193fSMichael Walle * @nor: pointer to 'struct spi_nor' 168cad3193fSMichael Walle * @region: OTP region 169cad3193fSMichael Walle * 170cad3193fSMichael Walle * Lock the OTP region by writing the status register-2. This method is used on 171cad3193fSMichael Walle * GigaDevice and Winbond flashes. 172cad3193fSMichael Walle * 173cad3193fSMichael Walle * Return: 0 on success, -errno otherwise. 174cad3193fSMichael Walle */ 175cad3193fSMichael Walle int spi_nor_otp_lock_sr2(struct spi_nor *nor, unsigned int region) 176cad3193fSMichael Walle { 177cad3193fSMichael Walle u8 *cr = nor->bouncebuf; 178cad3193fSMichael Walle int ret, lock_bit; 179cad3193fSMichael Walle 180cad3193fSMichael Walle lock_bit = spi_nor_otp_lock_bit_cr(region); 181cad3193fSMichael Walle if (lock_bit < 0) 182cad3193fSMichael Walle return lock_bit; 183cad3193fSMichael Walle 184cad3193fSMichael Walle ret = spi_nor_read_cr(nor, cr); 185cad3193fSMichael Walle if (ret) 186cad3193fSMichael Walle return ret; 187cad3193fSMichael Walle 188cad3193fSMichael Walle /* no need to write the register if region is already locked */ 189cad3193fSMichael Walle if (cr[0] & lock_bit) 190cad3193fSMichael Walle return 0; 191cad3193fSMichael Walle 192cad3193fSMichael Walle cr[0] |= lock_bit; 193cad3193fSMichael Walle 194cad3193fSMichael Walle return spi_nor_write_16bit_cr_and_check(nor, cr[0]); 195cad3193fSMichael Walle } 196cad3193fSMichael Walle 197cad3193fSMichael Walle /** 198cad3193fSMichael Walle * spi_nor_otp_is_locked_sr2() - get the OTP region lock status 199cad3193fSMichael Walle * @nor: pointer to 'struct spi_nor' 200cad3193fSMichael Walle * @region: OTP region 201cad3193fSMichael Walle * 202cad3193fSMichael Walle * Retrieve the OTP region lock bit by reading the status register-2. This 203cad3193fSMichael Walle * method is used on GigaDevice and Winbond flashes. 204cad3193fSMichael Walle * 205cad3193fSMichael Walle * Return: 0 on success, -errno otherwise. 206cad3193fSMichael Walle */ 207cad3193fSMichael Walle int spi_nor_otp_is_locked_sr2(struct spi_nor *nor, unsigned int region) 208cad3193fSMichael Walle { 209cad3193fSMichael Walle u8 *cr = nor->bouncebuf; 210cad3193fSMichael Walle int ret, lock_bit; 211cad3193fSMichael Walle 212cad3193fSMichael Walle lock_bit = spi_nor_otp_lock_bit_cr(region); 213cad3193fSMichael Walle if (lock_bit < 0) 214cad3193fSMichael Walle return lock_bit; 215cad3193fSMichael Walle 216cad3193fSMichael Walle ret = spi_nor_read_cr(nor, cr); 217cad3193fSMichael Walle if (ret) 218cad3193fSMichael Walle return ret; 219cad3193fSMichael Walle 220cad3193fSMichael Walle return cr[0] & lock_bit; 221cad3193fSMichael Walle } 222cad3193fSMichael Walle 223069089acSMichael Walle static loff_t spi_nor_otp_region_start(const struct spi_nor *nor, unsigned int region) 224069089acSMichael Walle { 225069089acSMichael Walle const struct spi_nor_otp_organization *org = nor->params->otp.org; 226069089acSMichael Walle 227069089acSMichael Walle return org->base + region * org->offset; 228069089acSMichael Walle } 229069089acSMichael Walle 230069089acSMichael Walle static size_t spi_nor_otp_size(struct spi_nor *nor) 231069089acSMichael Walle { 232069089acSMichael Walle return spi_nor_otp_n_regions(nor) * spi_nor_otp_region_len(nor); 233069089acSMichael Walle } 234069089acSMichael Walle 235069089acSMichael Walle /* Translate the file offsets from and to OTP regions. */ 236069089acSMichael Walle static loff_t spi_nor_otp_region_to_offset(struct spi_nor *nor, unsigned int region) 237069089acSMichael Walle { 238069089acSMichael Walle return region * spi_nor_otp_region_len(nor); 239069089acSMichael Walle } 240069089acSMichael Walle 241069089acSMichael Walle static unsigned int spi_nor_otp_offset_to_region(struct spi_nor *nor, loff_t ofs) 242069089acSMichael Walle { 243069089acSMichael Walle return div64_u64(ofs, spi_nor_otp_region_len(nor)); 244069089acSMichael Walle } 245069089acSMichael Walle 246069089acSMichael Walle static int spi_nor_mtd_otp_info(struct mtd_info *mtd, size_t len, 247069089acSMichael Walle size_t *retlen, struct otp_info *buf) 248069089acSMichael Walle { 249069089acSMichael Walle struct spi_nor *nor = mtd_to_spi_nor(mtd); 250069089acSMichael Walle const struct spi_nor_otp_ops *ops = nor->params->otp.ops; 251069089acSMichael Walle unsigned int n_regions = spi_nor_otp_n_regions(nor); 252069089acSMichael Walle unsigned int i; 253069089acSMichael Walle int ret, locked; 254069089acSMichael Walle 255069089acSMichael Walle if (len < n_regions * sizeof(*buf)) 256069089acSMichael Walle return -ENOSPC; 257069089acSMichael Walle 258069089acSMichael Walle ret = spi_nor_lock_and_prep(nor); 259069089acSMichael Walle if (ret) 260069089acSMichael Walle return ret; 261069089acSMichael Walle 262069089acSMichael Walle for (i = 0; i < n_regions; i++) { 263069089acSMichael Walle buf->start = spi_nor_otp_region_to_offset(nor, i); 264069089acSMichael Walle buf->length = spi_nor_otp_region_len(nor); 265069089acSMichael Walle 266069089acSMichael Walle locked = ops->is_locked(nor, i); 267069089acSMichael Walle if (locked < 0) { 268069089acSMichael Walle ret = locked; 269069089acSMichael Walle goto out; 270069089acSMichael Walle } 271069089acSMichael Walle 272069089acSMichael Walle buf->locked = !!locked; 273069089acSMichael Walle buf++; 274069089acSMichael Walle } 275069089acSMichael Walle 276069089acSMichael Walle *retlen = n_regions * sizeof(*buf); 277069089acSMichael Walle 278069089acSMichael Walle out: 279069089acSMichael Walle spi_nor_unlock_and_unprep(nor); 280069089acSMichael Walle 281069089acSMichael Walle return ret; 282069089acSMichael Walle } 283069089acSMichael Walle 284388161caSMichael Walle static int spi_nor_mtd_otp_range_is_locked(struct spi_nor *nor, loff_t ofs, 285388161caSMichael Walle size_t len) 286388161caSMichael Walle { 287388161caSMichael Walle const struct spi_nor_otp_ops *ops = nor->params->otp.ops; 288388161caSMichael Walle unsigned int region; 289388161caSMichael Walle int locked; 290388161caSMichael Walle 291388161caSMichael Walle /* 292388161caSMichael Walle * If any of the affected OTP regions are locked the entire range is 293388161caSMichael Walle * considered locked. 294388161caSMichael Walle */ 295388161caSMichael Walle for (region = spi_nor_otp_offset_to_region(nor, ofs); 296388161caSMichael Walle region <= spi_nor_otp_offset_to_region(nor, ofs + len - 1); 297388161caSMichael Walle region++) { 298388161caSMichael Walle locked = ops->is_locked(nor, region); 299388161caSMichael Walle /* take the branch it is locked or in case of an error */ 300388161caSMichael Walle if (locked) 301388161caSMichael Walle return locked; 302388161caSMichael Walle } 303388161caSMichael Walle 304388161caSMichael Walle return 0; 305388161caSMichael Walle } 306388161caSMichael Walle 307069089acSMichael Walle static int spi_nor_mtd_otp_read_write(struct mtd_info *mtd, loff_t ofs, 308069089acSMichael Walle size_t total_len, size_t *retlen, 3091df1fc8cSTudor Ambarus const u8 *buf, bool is_write) 310069089acSMichael Walle { 311069089acSMichael Walle struct spi_nor *nor = mtd_to_spi_nor(mtd); 312069089acSMichael Walle const struct spi_nor_otp_ops *ops = nor->params->otp.ops; 313069089acSMichael Walle const size_t rlen = spi_nor_otp_region_len(nor); 314069089acSMichael Walle loff_t rstart, rofs; 315069089acSMichael Walle unsigned int region; 316069089acSMichael Walle size_t len; 317069089acSMichael Walle int ret; 318069089acSMichael Walle 319069089acSMichael Walle if (ofs < 0 || ofs >= spi_nor_otp_size(nor)) 320069089acSMichael Walle return 0; 321069089acSMichael Walle 322388161caSMichael Walle /* don't access beyond the end */ 323388161caSMichael Walle total_len = min_t(size_t, total_len, spi_nor_otp_size(nor) - ofs); 324388161caSMichael Walle 325388161caSMichael Walle if (!total_len) 326388161caSMichael Walle return 0; 327388161caSMichael Walle 328069089acSMichael Walle ret = spi_nor_lock_and_prep(nor); 329069089acSMichael Walle if (ret) 330069089acSMichael Walle return ret; 331069089acSMichael Walle 332388161caSMichael Walle if (is_write) { 333388161caSMichael Walle ret = spi_nor_mtd_otp_range_is_locked(nor, ofs, total_len); 334388161caSMichael Walle if (ret < 0) { 335388161caSMichael Walle goto out; 336388161caSMichael Walle } else if (ret) { 337388161caSMichael Walle ret = -EROFS; 338388161caSMichael Walle goto out; 339388161caSMichael Walle } 340388161caSMichael Walle } 341069089acSMichael Walle 342069089acSMichael Walle while (total_len) { 343069089acSMichael Walle /* 344069089acSMichael Walle * The OTP regions are mapped into a contiguous area starting 345069089acSMichael Walle * at 0 as expected by the MTD layer. This will map the MTD 346069089acSMichael Walle * file offsets to the address of an OTP region as used in the 347069089acSMichael Walle * actual SPI commands. 348069089acSMichael Walle */ 349069089acSMichael Walle region = spi_nor_otp_offset_to_region(nor, ofs); 350069089acSMichael Walle rstart = spi_nor_otp_region_start(nor, region); 351069089acSMichael Walle 352069089acSMichael Walle /* 353069089acSMichael Walle * The size of a OTP region is expected to be a power of two, 354069089acSMichael Walle * thus we can just mask the lower bits and get the offset into 355069089acSMichael Walle * a region. 356069089acSMichael Walle */ 357069089acSMichael Walle rofs = ofs & (rlen - 1); 358069089acSMichael Walle 359069089acSMichael Walle /* don't access beyond one OTP region */ 360069089acSMichael Walle len = min_t(size_t, total_len, rlen - rofs); 361069089acSMichael Walle 362069089acSMichael Walle if (is_write) 363069089acSMichael Walle ret = ops->write(nor, rstart + rofs, len, buf); 364069089acSMichael Walle else 3651df1fc8cSTudor Ambarus ret = ops->read(nor, rstart + rofs, len, (u8 *)buf); 366069089acSMichael Walle if (ret == 0) 367069089acSMichael Walle ret = -EIO; 368069089acSMichael Walle if (ret < 0) 369069089acSMichael Walle goto out; 370069089acSMichael Walle 371069089acSMichael Walle *retlen += ret; 372069089acSMichael Walle ofs += ret; 373069089acSMichael Walle buf += ret; 374069089acSMichael Walle total_len -= ret; 375069089acSMichael Walle } 376069089acSMichael Walle ret = 0; 377069089acSMichael Walle 378069089acSMichael Walle out: 379069089acSMichael Walle spi_nor_unlock_and_unprep(nor); 380069089acSMichael Walle return ret; 381069089acSMichael Walle } 382069089acSMichael Walle 383069089acSMichael Walle static int spi_nor_mtd_otp_read(struct mtd_info *mtd, loff_t from, size_t len, 384069089acSMichael Walle size_t *retlen, u8 *buf) 385069089acSMichael Walle { 386069089acSMichael Walle return spi_nor_mtd_otp_read_write(mtd, from, len, retlen, buf, false); 387069089acSMichael Walle } 388069089acSMichael Walle 389069089acSMichael Walle static int spi_nor_mtd_otp_write(struct mtd_info *mtd, loff_t to, size_t len, 3901df1fc8cSTudor Ambarus size_t *retlen, const u8 *buf) 391069089acSMichael Walle { 392069089acSMichael Walle return spi_nor_mtd_otp_read_write(mtd, to, len, retlen, buf, true); 393069089acSMichael Walle } 394069089acSMichael Walle 395*c6ec3e1eSMichael Walle static int spi_nor_mtd_otp_erase(struct mtd_info *mtd, loff_t from, size_t len) 396*c6ec3e1eSMichael Walle { 397*c6ec3e1eSMichael Walle struct spi_nor *nor = mtd_to_spi_nor(mtd); 398*c6ec3e1eSMichael Walle const struct spi_nor_otp_ops *ops = nor->params->otp.ops; 399*c6ec3e1eSMichael Walle const size_t rlen = spi_nor_otp_region_len(nor); 400*c6ec3e1eSMichael Walle unsigned int region; 401*c6ec3e1eSMichael Walle loff_t rstart; 402*c6ec3e1eSMichael Walle int ret; 403*c6ec3e1eSMichael Walle 404*c6ec3e1eSMichael Walle /* OTP erase is optional */ 405*c6ec3e1eSMichael Walle if (!ops->erase) 406*c6ec3e1eSMichael Walle return -EOPNOTSUPP; 407*c6ec3e1eSMichael Walle 408*c6ec3e1eSMichael Walle if (!len) 409*c6ec3e1eSMichael Walle return 0; 410*c6ec3e1eSMichael Walle 411*c6ec3e1eSMichael Walle if (from < 0 || (from + len) > spi_nor_otp_size(nor)) 412*c6ec3e1eSMichael Walle return -EINVAL; 413*c6ec3e1eSMichael Walle 414*c6ec3e1eSMichael Walle /* the user has to explicitly ask for whole regions */ 415*c6ec3e1eSMichael Walle if (!IS_ALIGNED(len, rlen) || !IS_ALIGNED(from, rlen)) 416*c6ec3e1eSMichael Walle return -EINVAL; 417*c6ec3e1eSMichael Walle 418*c6ec3e1eSMichael Walle ret = spi_nor_lock_and_prep(nor); 419*c6ec3e1eSMichael Walle if (ret) 420*c6ec3e1eSMichael Walle return ret; 421*c6ec3e1eSMichael Walle 422*c6ec3e1eSMichael Walle ret = spi_nor_mtd_otp_range_is_locked(nor, from, len); 423*c6ec3e1eSMichael Walle if (ret < 0) { 424*c6ec3e1eSMichael Walle goto out; 425*c6ec3e1eSMichael Walle } else if (ret) { 426*c6ec3e1eSMichael Walle ret = -EROFS; 427*c6ec3e1eSMichael Walle goto out; 428*c6ec3e1eSMichael Walle } 429*c6ec3e1eSMichael Walle 430*c6ec3e1eSMichael Walle while (len) { 431*c6ec3e1eSMichael Walle region = spi_nor_otp_offset_to_region(nor, from); 432*c6ec3e1eSMichael Walle rstart = spi_nor_otp_region_start(nor, region); 433*c6ec3e1eSMichael Walle 434*c6ec3e1eSMichael Walle ret = ops->erase(nor, rstart); 435*c6ec3e1eSMichael Walle if (ret) 436*c6ec3e1eSMichael Walle goto out; 437*c6ec3e1eSMichael Walle 438*c6ec3e1eSMichael Walle len -= rlen; 439*c6ec3e1eSMichael Walle from += rlen; 440*c6ec3e1eSMichael Walle } 441*c6ec3e1eSMichael Walle 442*c6ec3e1eSMichael Walle out: 443*c6ec3e1eSMichael Walle spi_nor_unlock_and_unprep(nor); 444*c6ec3e1eSMichael Walle 445*c6ec3e1eSMichael Walle return ret; 446*c6ec3e1eSMichael Walle } 447*c6ec3e1eSMichael Walle 448069089acSMichael Walle static int spi_nor_mtd_otp_lock(struct mtd_info *mtd, loff_t from, size_t len) 449069089acSMichael Walle { 450069089acSMichael Walle struct spi_nor *nor = mtd_to_spi_nor(mtd); 451069089acSMichael Walle const struct spi_nor_otp_ops *ops = nor->params->otp.ops; 452069089acSMichael Walle const size_t rlen = spi_nor_otp_region_len(nor); 453069089acSMichael Walle unsigned int region; 454069089acSMichael Walle int ret; 455069089acSMichael Walle 456069089acSMichael Walle if (from < 0 || (from + len) > spi_nor_otp_size(nor)) 457069089acSMichael Walle return -EINVAL; 458069089acSMichael Walle 459069089acSMichael Walle /* the user has to explicitly ask for whole regions */ 460069089acSMichael Walle if (!IS_ALIGNED(len, rlen) || !IS_ALIGNED(from, rlen)) 461069089acSMichael Walle return -EINVAL; 462069089acSMichael Walle 463069089acSMichael Walle ret = spi_nor_lock_and_prep(nor); 464069089acSMichael Walle if (ret) 465069089acSMichael Walle return ret; 466069089acSMichael Walle 467069089acSMichael Walle while (len) { 468069089acSMichael Walle region = spi_nor_otp_offset_to_region(nor, from); 469069089acSMichael Walle ret = ops->lock(nor, region); 470069089acSMichael Walle if (ret) 471069089acSMichael Walle goto out; 472069089acSMichael Walle 473069089acSMichael Walle len -= rlen; 474069089acSMichael Walle from += rlen; 475069089acSMichael Walle } 476069089acSMichael Walle 477069089acSMichael Walle out: 478069089acSMichael Walle spi_nor_unlock_and_unprep(nor); 479069089acSMichael Walle 480069089acSMichael Walle return ret; 481069089acSMichael Walle } 482069089acSMichael Walle 483069089acSMichael Walle void spi_nor_otp_init(struct spi_nor *nor) 484069089acSMichael Walle { 485069089acSMichael Walle struct mtd_info *mtd = &nor->mtd; 486069089acSMichael Walle 487069089acSMichael Walle if (!nor->params->otp.ops) 488069089acSMichael Walle return; 489069089acSMichael Walle 490069089acSMichael Walle if (WARN_ON(!is_power_of_2(spi_nor_otp_region_len(nor)))) 491069089acSMichael Walle return; 492069089acSMichael Walle 493069089acSMichael Walle /* 494069089acSMichael Walle * We only support user_prot callbacks (yet). 495069089acSMichael Walle * 496069089acSMichael Walle * Some SPI NOR flashes like Macronix ones can be ordered in two 497069089acSMichael Walle * different variants. One with a factory locked OTP area and one where 498069089acSMichael Walle * it is left to the user to write to it. The factory locked OTP is 499069089acSMichael Walle * usually preprogrammed with an "electrical serial number". We don't 500069089acSMichael Walle * support these for now. 501069089acSMichael Walle */ 502069089acSMichael Walle mtd->_get_user_prot_info = spi_nor_mtd_otp_info; 503069089acSMichael Walle mtd->_read_user_prot_reg = spi_nor_mtd_otp_read; 504069089acSMichael Walle mtd->_write_user_prot_reg = spi_nor_mtd_otp_write; 505069089acSMichael Walle mtd->_lock_user_prot_reg = spi_nor_mtd_otp_lock; 506*c6ec3e1eSMichael Walle mtd->_erase_user_prot_reg = spi_nor_mtd_otp_erase; 507069089acSMichael Walle } 508