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 17*cad3193fSMichael Walle /** 18*cad3193fSMichael Walle * spi_nor_otp_read_secr() - read OTP data 19*cad3193fSMichael Walle * @nor: pointer to 'struct spi_nor' 20*cad3193fSMichael Walle * @from: offset to read from 21*cad3193fSMichael Walle * @len: number of bytes to read 22*cad3193fSMichael Walle * @buf: pointer to dst buffer 23*cad3193fSMichael Walle * 24*cad3193fSMichael Walle * Read OTP data from one region by using the SPINOR_OP_RSECR commands. This 25*cad3193fSMichael Walle * method is used on GigaDevice and Winbond flashes. 26*cad3193fSMichael Walle * 27*cad3193fSMichael Walle * Return: number of bytes read successfully, -errno otherwise 28*cad3193fSMichael Walle */ 29*cad3193fSMichael Walle int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t len, u8 *buf) 30*cad3193fSMichael Walle { 31*cad3193fSMichael Walle u8 addr_width, read_opcode, read_dummy; 32*cad3193fSMichael Walle struct spi_mem_dirmap_desc *rdesc; 33*cad3193fSMichael Walle enum spi_nor_protocol read_proto; 34*cad3193fSMichael Walle int ret; 35*cad3193fSMichael Walle 36*cad3193fSMichael Walle read_opcode = nor->read_opcode; 37*cad3193fSMichael Walle addr_width = nor->addr_width; 38*cad3193fSMichael Walle read_dummy = nor->read_dummy; 39*cad3193fSMichael Walle read_proto = nor->read_proto; 40*cad3193fSMichael Walle rdesc = nor->dirmap.rdesc; 41*cad3193fSMichael Walle 42*cad3193fSMichael Walle nor->read_opcode = SPINOR_OP_RSECR; 43*cad3193fSMichael Walle nor->addr_width = 3; 44*cad3193fSMichael Walle nor->read_dummy = 8; 45*cad3193fSMichael Walle nor->read_proto = SNOR_PROTO_1_1_1; 46*cad3193fSMichael Walle nor->dirmap.rdesc = NULL; 47*cad3193fSMichael Walle 48*cad3193fSMichael Walle ret = spi_nor_read_data(nor, addr, len, buf); 49*cad3193fSMichael Walle 50*cad3193fSMichael Walle nor->read_opcode = read_opcode; 51*cad3193fSMichael Walle nor->addr_width = addr_width; 52*cad3193fSMichael Walle nor->read_dummy = read_dummy; 53*cad3193fSMichael Walle nor->read_proto = read_proto; 54*cad3193fSMichael Walle nor->dirmap.rdesc = rdesc; 55*cad3193fSMichael Walle 56*cad3193fSMichael Walle return ret; 57*cad3193fSMichael Walle } 58*cad3193fSMichael Walle 59*cad3193fSMichael Walle /** 60*cad3193fSMichael Walle * spi_nor_otp_write_secr() - write OTP data 61*cad3193fSMichael Walle * @nor: pointer to 'struct spi_nor' 62*cad3193fSMichael Walle * @to: offset to write to 63*cad3193fSMichael Walle * @len: number of bytes to write 64*cad3193fSMichael Walle * @buf: pointer to src buffer 65*cad3193fSMichael Walle * 66*cad3193fSMichael Walle * Write OTP data to one region by using the SPINOR_OP_PSECR commands. This 67*cad3193fSMichael Walle * method is used on GigaDevice and Winbond flashes. 68*cad3193fSMichael Walle * 69*cad3193fSMichael Walle * Please note, the write must not span multiple OTP regions. 70*cad3193fSMichael Walle * 71*cad3193fSMichael Walle * Return: number of bytes written successfully, -errno otherwise 72*cad3193fSMichael Walle */ 73*cad3193fSMichael Walle int spi_nor_otp_write_secr(struct spi_nor *nor, loff_t addr, size_t len, u8 *buf) 74*cad3193fSMichael Walle { 75*cad3193fSMichael Walle enum spi_nor_protocol write_proto; 76*cad3193fSMichael Walle struct spi_mem_dirmap_desc *wdesc; 77*cad3193fSMichael Walle u8 addr_width, program_opcode; 78*cad3193fSMichael Walle int ret, written; 79*cad3193fSMichael Walle 80*cad3193fSMichael Walle program_opcode = nor->program_opcode; 81*cad3193fSMichael Walle addr_width = nor->addr_width; 82*cad3193fSMichael Walle write_proto = nor->write_proto; 83*cad3193fSMichael Walle wdesc = nor->dirmap.wdesc; 84*cad3193fSMichael Walle 85*cad3193fSMichael Walle nor->program_opcode = SPINOR_OP_PSECR; 86*cad3193fSMichael Walle nor->addr_width = 3; 87*cad3193fSMichael Walle nor->write_proto = SNOR_PROTO_1_1_1; 88*cad3193fSMichael Walle nor->dirmap.wdesc = NULL; 89*cad3193fSMichael Walle 90*cad3193fSMichael Walle /* 91*cad3193fSMichael Walle * We only support a write to one single page. For now all winbond 92*cad3193fSMichael Walle * flashes only have one page per OTP region. 93*cad3193fSMichael Walle */ 94*cad3193fSMichael Walle ret = spi_nor_write_enable(nor); 95*cad3193fSMichael Walle if (ret) 96*cad3193fSMichael Walle goto out; 97*cad3193fSMichael Walle 98*cad3193fSMichael Walle written = spi_nor_write_data(nor, addr, len, buf); 99*cad3193fSMichael Walle if (written < 0) 100*cad3193fSMichael Walle goto out; 101*cad3193fSMichael Walle 102*cad3193fSMichael Walle ret = spi_nor_wait_till_ready(nor); 103*cad3193fSMichael Walle 104*cad3193fSMichael Walle out: 105*cad3193fSMichael Walle nor->program_opcode = program_opcode; 106*cad3193fSMichael Walle nor->addr_width = addr_width; 107*cad3193fSMichael Walle nor->write_proto = write_proto; 108*cad3193fSMichael Walle nor->dirmap.wdesc = wdesc; 109*cad3193fSMichael Walle 110*cad3193fSMichael Walle return ret ?: written; 111*cad3193fSMichael Walle } 112*cad3193fSMichael Walle 113*cad3193fSMichael Walle static int spi_nor_otp_lock_bit_cr(unsigned int region) 114*cad3193fSMichael Walle { 115*cad3193fSMichael Walle static const int lock_bits[] = { SR2_LB1, SR2_LB2, SR2_LB3 }; 116*cad3193fSMichael Walle 117*cad3193fSMichael Walle if (region >= ARRAY_SIZE(lock_bits)) 118*cad3193fSMichael Walle return -EINVAL; 119*cad3193fSMichael Walle 120*cad3193fSMichael Walle return lock_bits[region]; 121*cad3193fSMichael Walle } 122*cad3193fSMichael Walle 123*cad3193fSMichael Walle /** 124*cad3193fSMichael Walle * spi_nor_otp_lock_sr2() - lock the OTP region 125*cad3193fSMichael Walle * @nor: pointer to 'struct spi_nor' 126*cad3193fSMichael Walle * @region: OTP region 127*cad3193fSMichael Walle * 128*cad3193fSMichael Walle * Lock the OTP region by writing the status register-2. This method is used on 129*cad3193fSMichael Walle * GigaDevice and Winbond flashes. 130*cad3193fSMichael Walle * 131*cad3193fSMichael Walle * Return: 0 on success, -errno otherwise. 132*cad3193fSMichael Walle */ 133*cad3193fSMichael Walle int spi_nor_otp_lock_sr2(struct spi_nor *nor, unsigned int region) 134*cad3193fSMichael Walle { 135*cad3193fSMichael Walle u8 *cr = nor->bouncebuf; 136*cad3193fSMichael Walle int ret, lock_bit; 137*cad3193fSMichael Walle 138*cad3193fSMichael Walle lock_bit = spi_nor_otp_lock_bit_cr(region); 139*cad3193fSMichael Walle if (lock_bit < 0) 140*cad3193fSMichael Walle return lock_bit; 141*cad3193fSMichael Walle 142*cad3193fSMichael Walle ret = spi_nor_read_cr(nor, cr); 143*cad3193fSMichael Walle if (ret) 144*cad3193fSMichael Walle return ret; 145*cad3193fSMichael Walle 146*cad3193fSMichael Walle /* no need to write the register if region is already locked */ 147*cad3193fSMichael Walle if (cr[0] & lock_bit) 148*cad3193fSMichael Walle return 0; 149*cad3193fSMichael Walle 150*cad3193fSMichael Walle cr[0] |= lock_bit; 151*cad3193fSMichael Walle 152*cad3193fSMichael Walle return spi_nor_write_16bit_cr_and_check(nor, cr[0]); 153*cad3193fSMichael Walle } 154*cad3193fSMichael Walle 155*cad3193fSMichael Walle /** 156*cad3193fSMichael Walle * spi_nor_otp_is_locked_sr2() - get the OTP region lock status 157*cad3193fSMichael Walle * @nor: pointer to 'struct spi_nor' 158*cad3193fSMichael Walle * @region: OTP region 159*cad3193fSMichael Walle * 160*cad3193fSMichael Walle * Retrieve the OTP region lock bit by reading the status register-2. This 161*cad3193fSMichael Walle * method is used on GigaDevice and Winbond flashes. 162*cad3193fSMichael Walle * 163*cad3193fSMichael Walle * Return: 0 on success, -errno otherwise. 164*cad3193fSMichael Walle */ 165*cad3193fSMichael Walle int spi_nor_otp_is_locked_sr2(struct spi_nor *nor, unsigned int region) 166*cad3193fSMichael Walle { 167*cad3193fSMichael Walle u8 *cr = nor->bouncebuf; 168*cad3193fSMichael Walle int ret, lock_bit; 169*cad3193fSMichael Walle 170*cad3193fSMichael Walle lock_bit = spi_nor_otp_lock_bit_cr(region); 171*cad3193fSMichael Walle if (lock_bit < 0) 172*cad3193fSMichael Walle return lock_bit; 173*cad3193fSMichael Walle 174*cad3193fSMichael Walle ret = spi_nor_read_cr(nor, cr); 175*cad3193fSMichael Walle if (ret) 176*cad3193fSMichael Walle return ret; 177*cad3193fSMichael Walle 178*cad3193fSMichael Walle return cr[0] & lock_bit; 179*cad3193fSMichael Walle } 180*cad3193fSMichael Walle 181069089acSMichael Walle static loff_t spi_nor_otp_region_start(const struct spi_nor *nor, unsigned int region) 182069089acSMichael Walle { 183069089acSMichael Walle const struct spi_nor_otp_organization *org = nor->params->otp.org; 184069089acSMichael Walle 185069089acSMichael Walle return org->base + region * org->offset; 186069089acSMichael Walle } 187069089acSMichael Walle 188069089acSMichael Walle static size_t spi_nor_otp_size(struct spi_nor *nor) 189069089acSMichael Walle { 190069089acSMichael Walle return spi_nor_otp_n_regions(nor) * spi_nor_otp_region_len(nor); 191069089acSMichael Walle } 192069089acSMichael Walle 193069089acSMichael Walle /* Translate the file offsets from and to OTP regions. */ 194069089acSMichael Walle static loff_t spi_nor_otp_region_to_offset(struct spi_nor *nor, unsigned int region) 195069089acSMichael Walle { 196069089acSMichael Walle return region * spi_nor_otp_region_len(nor); 197069089acSMichael Walle } 198069089acSMichael Walle 199069089acSMichael Walle static unsigned int spi_nor_otp_offset_to_region(struct spi_nor *nor, loff_t ofs) 200069089acSMichael Walle { 201069089acSMichael Walle return div64_u64(ofs, spi_nor_otp_region_len(nor)); 202069089acSMichael Walle } 203069089acSMichael Walle 204069089acSMichael Walle static int spi_nor_mtd_otp_info(struct mtd_info *mtd, size_t len, 205069089acSMichael Walle size_t *retlen, struct otp_info *buf) 206069089acSMichael Walle { 207069089acSMichael Walle struct spi_nor *nor = mtd_to_spi_nor(mtd); 208069089acSMichael Walle const struct spi_nor_otp_ops *ops = nor->params->otp.ops; 209069089acSMichael Walle unsigned int n_regions = spi_nor_otp_n_regions(nor); 210069089acSMichael Walle unsigned int i; 211069089acSMichael Walle int ret, locked; 212069089acSMichael Walle 213069089acSMichael Walle if (len < n_regions * sizeof(*buf)) 214069089acSMichael Walle return -ENOSPC; 215069089acSMichael Walle 216069089acSMichael Walle ret = spi_nor_lock_and_prep(nor); 217069089acSMichael Walle if (ret) 218069089acSMichael Walle return ret; 219069089acSMichael Walle 220069089acSMichael Walle for (i = 0; i < n_regions; i++) { 221069089acSMichael Walle buf->start = spi_nor_otp_region_to_offset(nor, i); 222069089acSMichael Walle buf->length = spi_nor_otp_region_len(nor); 223069089acSMichael Walle 224069089acSMichael Walle locked = ops->is_locked(nor, i); 225069089acSMichael Walle if (locked < 0) { 226069089acSMichael Walle ret = locked; 227069089acSMichael Walle goto out; 228069089acSMichael Walle } 229069089acSMichael Walle 230069089acSMichael Walle buf->locked = !!locked; 231069089acSMichael Walle buf++; 232069089acSMichael Walle } 233069089acSMichael Walle 234069089acSMichael Walle *retlen = n_regions * sizeof(*buf); 235069089acSMichael Walle 236069089acSMichael Walle out: 237069089acSMichael Walle spi_nor_unlock_and_unprep(nor); 238069089acSMichael Walle 239069089acSMichael Walle return ret; 240069089acSMichael Walle } 241069089acSMichael Walle 242069089acSMichael Walle static int spi_nor_mtd_otp_read_write(struct mtd_info *mtd, loff_t ofs, 243069089acSMichael Walle size_t total_len, size_t *retlen, 244069089acSMichael Walle u8 *buf, bool is_write) 245069089acSMichael Walle { 246069089acSMichael Walle struct spi_nor *nor = mtd_to_spi_nor(mtd); 247069089acSMichael Walle const struct spi_nor_otp_ops *ops = nor->params->otp.ops; 248069089acSMichael Walle const size_t rlen = spi_nor_otp_region_len(nor); 249069089acSMichael Walle loff_t rstart, rofs; 250069089acSMichael Walle unsigned int region; 251069089acSMichael Walle size_t len; 252069089acSMichael Walle int ret; 253069089acSMichael Walle 254069089acSMichael Walle if (ofs < 0 || ofs >= spi_nor_otp_size(nor)) 255069089acSMichael Walle return 0; 256069089acSMichael Walle 257069089acSMichael Walle ret = spi_nor_lock_and_prep(nor); 258069089acSMichael Walle if (ret) 259069089acSMichael Walle return ret; 260069089acSMichael Walle 261069089acSMichael Walle /* don't access beyond the end */ 262069089acSMichael Walle total_len = min_t(size_t, total_len, spi_nor_otp_size(nor) - ofs); 263069089acSMichael Walle 264069089acSMichael Walle *retlen = 0; 265069089acSMichael Walle while (total_len) { 266069089acSMichael Walle /* 267069089acSMichael Walle * The OTP regions are mapped into a contiguous area starting 268069089acSMichael Walle * at 0 as expected by the MTD layer. This will map the MTD 269069089acSMichael Walle * file offsets to the address of an OTP region as used in the 270069089acSMichael Walle * actual SPI commands. 271069089acSMichael Walle */ 272069089acSMichael Walle region = spi_nor_otp_offset_to_region(nor, ofs); 273069089acSMichael Walle rstart = spi_nor_otp_region_start(nor, region); 274069089acSMichael Walle 275069089acSMichael Walle /* 276069089acSMichael Walle * The size of a OTP region is expected to be a power of two, 277069089acSMichael Walle * thus we can just mask the lower bits and get the offset into 278069089acSMichael Walle * a region. 279069089acSMichael Walle */ 280069089acSMichael Walle rofs = ofs & (rlen - 1); 281069089acSMichael Walle 282069089acSMichael Walle /* don't access beyond one OTP region */ 283069089acSMichael Walle len = min_t(size_t, total_len, rlen - rofs); 284069089acSMichael Walle 285069089acSMichael Walle if (is_write) 286069089acSMichael Walle ret = ops->write(nor, rstart + rofs, len, buf); 287069089acSMichael Walle else 288069089acSMichael Walle ret = ops->read(nor, rstart + rofs, len, buf); 289069089acSMichael Walle if (ret == 0) 290069089acSMichael Walle ret = -EIO; 291069089acSMichael Walle if (ret < 0) 292069089acSMichael Walle goto out; 293069089acSMichael Walle 294069089acSMichael Walle *retlen += ret; 295069089acSMichael Walle ofs += ret; 296069089acSMichael Walle buf += ret; 297069089acSMichael Walle total_len -= ret; 298069089acSMichael Walle } 299069089acSMichael Walle ret = 0; 300069089acSMichael Walle 301069089acSMichael Walle out: 302069089acSMichael Walle spi_nor_unlock_and_unprep(nor); 303069089acSMichael Walle return ret; 304069089acSMichael Walle } 305069089acSMichael Walle 306069089acSMichael Walle static int spi_nor_mtd_otp_read(struct mtd_info *mtd, loff_t from, size_t len, 307069089acSMichael Walle size_t *retlen, u8 *buf) 308069089acSMichael Walle { 309069089acSMichael Walle return spi_nor_mtd_otp_read_write(mtd, from, len, retlen, buf, false); 310069089acSMichael Walle } 311069089acSMichael Walle 312069089acSMichael Walle static int spi_nor_mtd_otp_write(struct mtd_info *mtd, loff_t to, size_t len, 313069089acSMichael Walle size_t *retlen, u8 *buf) 314069089acSMichael Walle { 315069089acSMichael Walle return spi_nor_mtd_otp_read_write(mtd, to, len, retlen, buf, true); 316069089acSMichael Walle } 317069089acSMichael Walle 318069089acSMichael Walle static int spi_nor_mtd_otp_lock(struct mtd_info *mtd, loff_t from, size_t len) 319069089acSMichael Walle { 320069089acSMichael Walle struct spi_nor *nor = mtd_to_spi_nor(mtd); 321069089acSMichael Walle const struct spi_nor_otp_ops *ops = nor->params->otp.ops; 322069089acSMichael Walle const size_t rlen = spi_nor_otp_region_len(nor); 323069089acSMichael Walle unsigned int region; 324069089acSMichael Walle int ret; 325069089acSMichael Walle 326069089acSMichael Walle if (from < 0 || (from + len) > spi_nor_otp_size(nor)) 327069089acSMichael Walle return -EINVAL; 328069089acSMichael Walle 329069089acSMichael Walle /* the user has to explicitly ask for whole regions */ 330069089acSMichael Walle if (!IS_ALIGNED(len, rlen) || !IS_ALIGNED(from, rlen)) 331069089acSMichael Walle return -EINVAL; 332069089acSMichael Walle 333069089acSMichael Walle ret = spi_nor_lock_and_prep(nor); 334069089acSMichael Walle if (ret) 335069089acSMichael Walle return ret; 336069089acSMichael Walle 337069089acSMichael Walle while (len) { 338069089acSMichael Walle region = spi_nor_otp_offset_to_region(nor, from); 339069089acSMichael Walle ret = ops->lock(nor, region); 340069089acSMichael Walle if (ret) 341069089acSMichael Walle goto out; 342069089acSMichael Walle 343069089acSMichael Walle len -= rlen; 344069089acSMichael Walle from += rlen; 345069089acSMichael Walle } 346069089acSMichael Walle 347069089acSMichael Walle out: 348069089acSMichael Walle spi_nor_unlock_and_unprep(nor); 349069089acSMichael Walle 350069089acSMichael Walle return ret; 351069089acSMichael Walle } 352069089acSMichael Walle 353069089acSMichael Walle void spi_nor_otp_init(struct spi_nor *nor) 354069089acSMichael Walle { 355069089acSMichael Walle struct mtd_info *mtd = &nor->mtd; 356069089acSMichael Walle 357069089acSMichael Walle if (!nor->params->otp.ops) 358069089acSMichael Walle return; 359069089acSMichael Walle 360069089acSMichael Walle if (WARN_ON(!is_power_of_2(spi_nor_otp_region_len(nor)))) 361069089acSMichael Walle return; 362069089acSMichael Walle 363069089acSMichael Walle /* 364069089acSMichael Walle * We only support user_prot callbacks (yet). 365069089acSMichael Walle * 366069089acSMichael Walle * Some SPI NOR flashes like Macronix ones can be ordered in two 367069089acSMichael Walle * different variants. One with a factory locked OTP area and one where 368069089acSMichael Walle * it is left to the user to write to it. The factory locked OTP is 369069089acSMichael Walle * usually preprogrammed with an "electrical serial number". We don't 370069089acSMichael Walle * support these for now. 371069089acSMichael Walle */ 372069089acSMichael Walle mtd->_get_user_prot_info = spi_nor_mtd_otp_info; 373069089acSMichael Walle mtd->_read_user_prot_reg = spi_nor_mtd_otp_read; 374069089acSMichael Walle mtd->_write_user_prot_reg = spi_nor_mtd_otp_write; 375069089acSMichael Walle mtd->_lock_user_prot_reg = spi_nor_mtd_otp_lock; 376069089acSMichael Walle } 377