xref: /openbmc/linux/drivers/mtd/spi-nor/otp.c (revision cad3193f)
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