1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <linux/io.h>
18 #include <linux/errno.h>
19 #include <linux/string.h>
20 
21 #include <brcm_hw_ids.h>
22 #include <chipcommon.h>
23 #include "aiutils.h"
24 #include "otp.h"
25 
26 #define OTPS_GUP_MASK		0x00000f00
27 #define OTPS_GUP_SHIFT		8
28 /* h/w subregion is programmed */
29 #define OTPS_GUP_HW		0x00000100
30 /* s/w subregion is programmed */
31 #define OTPS_GUP_SW		0x00000200
32 /* chipid/pkgopt subregion is programmed */
33 #define OTPS_GUP_CI		0x00000400
34 /* fuse subregion is programmed */
35 #define OTPS_GUP_FUSE		0x00000800
36 
37 /* Fields in otpprog in rev >= 21 */
38 #define OTPP_COL_MASK		0x000000ff
39 #define OTPP_COL_SHIFT		0
40 #define OTPP_ROW_MASK		0x0000ff00
41 #define OTPP_ROW_SHIFT		8
42 #define OTPP_OC_MASK		0x0f000000
43 #define OTPP_OC_SHIFT		24
44 #define OTPP_READERR		0x10000000
45 #define OTPP_VALUE_MASK		0x20000000
46 #define OTPP_VALUE_SHIFT	29
47 #define OTPP_START_BUSY		0x80000000
48 #define	OTPP_READ		0x40000000
49 
50 /* Opcodes for OTPP_OC field */
51 #define OTPPOC_READ		0
52 #define OTPPOC_BIT_PROG		1
53 #define OTPPOC_VERIFY		3
54 #define OTPPOC_INIT		4
55 #define OTPPOC_SET		5
56 #define OTPPOC_RESET		6
57 #define OTPPOC_OCST		7
58 #define OTPPOC_ROW_LOCK		8
59 #define OTPPOC_PRESCN_TEST	9
60 
61 #define OTPTYPE_IPX(ccrev)	((ccrev) == 21 || (ccrev) >= 23)
62 
63 #define OTPP_TRIES	10000000	/* # of tries for OTPP */
64 
65 #define MAXNUMRDES		9	/* Maximum OTP redundancy entries */
66 
67 /* Fixed size subregions sizes in words */
68 #define OTPGU_CI_SZ		2
69 
70 struct otpinfo;
71 
72 /* OTP function struct */
73 struct otp_fn_s {
74 	int (*init)(struct si_pub *sih, struct otpinfo *oi);
75 	int (*read_region)(struct otpinfo *oi, int region, u16 *data,
76 			   uint *wlen);
77 };
78 
79 struct otpinfo {
80 	struct bcma_device *core; /* chipc core */
81 	const struct otp_fn_s *fn;	/* OTP functions */
82 	struct si_pub *sih;		/* Saved sb handle */
83 
84 	/* IPX OTP section */
85 	u16 wsize;		/* Size of otp in words */
86 	u16 rows;		/* Geometry */
87 	u16 cols;		/* Geometry */
88 	u32 status;		/* Flag bits (lock/prog/rv).
89 				 * (Reflected only when OTP is power cycled)
90 				 */
91 	u16 hwbase;		/* hardware subregion offset */
92 	u16 hwlim;		/* hardware subregion boundary */
93 	u16 swbase;		/* software subregion offset */
94 	u16 swlim;		/* software subregion boundary */
95 	u16 fbase;		/* fuse subregion offset */
96 	u16 flim;		/* fuse subregion boundary */
97 	int otpgu_base;		/* offset to General Use Region */
98 };
99 
100 /* OTP layout */
101 /* CC revs 21, 24 and 27 OTP General Use Region word offset */
102 #define REVA4_OTPGU_BASE	12
103 
104 /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
105 #define REVB8_OTPGU_BASE	20
106 
107 /* CC rev 36 OTP General Use Region word offset */
108 #define REV36_OTPGU_BASE	12
109 
110 /* Subregion word offsets in General Use region */
111 #define OTPGU_HSB_OFF		0
112 #define OTPGU_SFB_OFF		1
113 #define OTPGU_CI_OFF		2
114 #define OTPGU_P_OFF		3
115 #define OTPGU_SROM_OFF		4
116 
117 /* Flag bit offsets in General Use region  */
118 #define OTPGU_HWP_OFF		60
119 #define OTPGU_SWP_OFF		61
120 #define OTPGU_CIP_OFF		62
121 #define OTPGU_FUSEP_OFF		63
122 #define OTPGU_CIP_MSK		0x4000
123 #define OTPGU_P_MSK		0xf000
124 #define OTPGU_P_SHIFT		(OTPGU_HWP_OFF % 16)
125 
126 /* OTP Size */
127 #define OTP_SZ_FU_324		((roundup(324, 8))/8)	/* 324 bits */
128 #define OTP_SZ_FU_288		(288/8)	/* 288 bits */
129 #define OTP_SZ_FU_216		(216/8)	/* 216 bits */
130 #define OTP_SZ_FU_72		(72/8)	/* 72 bits */
131 #define OTP_SZ_CHECKSUM		(16/8)	/* 16 bits */
132 #define OTP4315_SWREG_SZ	178	/* 178 bytes */
133 #define OTP_SZ_FU_144		(144/8)	/* 144 bits */
134 
135 static u16
ipxotp_otpr(struct otpinfo * oi,uint wn)136 ipxotp_otpr(struct otpinfo *oi, uint wn)
137 {
138 	return bcma_read16(oi->core,
139 			   CHIPCREGOFFS(sromotp[wn]));
140 }
141 
142 /*
143  * Calculate max HW/SW region byte size by subtracting fuse region
144  * and checksum size, osizew is oi->wsize (OTP size - GU size) in words
145  */
ipxotp_max_rgnsz(struct si_pub * sih,int osizew)146 static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
147 {
148 	int ret = 0;
149 
150 	switch (ai_get_chip_id(sih)) {
151 	case BCM43224_CHIP_ID:
152 	case BCM43225_CHIP_ID:
153 		ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
154 		break;
155 	case BCM4313_CHIP_ID:
156 		ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
157 		break;
158 	default:
159 		break;	/* Don't know about this chip */
160 	}
161 
162 	return ret;
163 }
164 
_ipxotp_init(struct otpinfo * oi)165 static void _ipxotp_init(struct otpinfo *oi)
166 {
167 	uint k;
168 	u32 otpp, st;
169 	int ccrev = ai_get_ccrev(oi->sih);
170 
171 
172 	/*
173 	 * record word offset of General Use Region
174 	 * for various chipcommon revs
175 	 */
176 	if (ccrev == 21 || ccrev == 24
177 	    || ccrev == 27) {
178 		oi->otpgu_base = REVA4_OTPGU_BASE;
179 	} else if (ccrev == 36) {
180 		/*
181 		 * OTP size greater than equal to 2KB (128 words),
182 		 * otpgu_base is similar to rev23
183 		 */
184 		if (oi->wsize >= 128)
185 			oi->otpgu_base = REVB8_OTPGU_BASE;
186 		else
187 			oi->otpgu_base = REV36_OTPGU_BASE;
188 	} else if (ccrev == 23 || ccrev >= 25) {
189 		oi->otpgu_base = REVB8_OTPGU_BASE;
190 	}
191 
192 	/* First issue an init command so the status is up to date */
193 	otpp =
194 	    OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
195 
196 	bcma_write32(oi->core, CHIPCREGOFFS(otpprog), otpp);
197 	st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
198 	for (k = 0; (st & OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
199 		st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
200 	if (k >= OTPP_TRIES)
201 		return;
202 
203 	/* Read OTP lock bits and subregion programmed indication bits */
204 	oi->status = bcma_read32(oi->core, CHIPCREGOFFS(otpstatus));
205 
206 	if ((ai_get_chip_id(oi->sih) == BCM43224_CHIP_ID)
207 	    || (ai_get_chip_id(oi->sih) == BCM43225_CHIP_ID)) {
208 		u32 p_bits;
209 		p_bits = (ipxotp_otpr(oi, oi->otpgu_base + OTPGU_P_OFF) &
210 			  OTPGU_P_MSK) >> OTPGU_P_SHIFT;
211 		oi->status |= (p_bits << OTPS_GUP_SHIFT);
212 	}
213 
214 	/*
215 	 * h/w region base and fuse region limit are fixed to
216 	 * the top and the bottom of the general use region.
217 	 * Everything else can be flexible.
218 	 */
219 	oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
220 	oi->hwlim = oi->wsize;
221 	if (oi->status & OTPS_GUP_HW) {
222 		oi->hwlim =
223 		    ipxotp_otpr(oi, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
224 		oi->swbase = oi->hwlim;
225 	} else
226 		oi->swbase = oi->hwbase;
227 
228 	/* subtract fuse and checksum from beginning */
229 	oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
230 
231 	if (oi->status & OTPS_GUP_SW) {
232 		oi->swlim =
233 		    ipxotp_otpr(oi, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
234 		oi->fbase = oi->swlim;
235 	} else
236 		oi->fbase = oi->swbase;
237 
238 	oi->flim = oi->wsize;
239 }
240 
ipxotp_init(struct si_pub * sih,struct otpinfo * oi)241 static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
242 {
243 	/* Make sure we're running IPX OTP */
244 	if (!OTPTYPE_IPX(ai_get_ccrev(sih)))
245 		return -EBADE;
246 
247 	/* Make sure OTP is not disabled */
248 	if (ai_is_otp_disabled(sih))
249 		return -EBADE;
250 
251 	/* Check for otp size */
252 	switch ((ai_get_cccaps(sih) & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
253 	case 0:
254 		/* Nothing there */
255 		return -EBADE;
256 	case 1:		/* 32x64 */
257 		oi->rows = 32;
258 		oi->cols = 64;
259 		oi->wsize = 128;
260 		break;
261 	case 2:		/* 64x64 */
262 		oi->rows = 64;
263 		oi->cols = 64;
264 		oi->wsize = 256;
265 		break;
266 	case 5:		/* 96x64 */
267 		oi->rows = 96;
268 		oi->cols = 64;
269 		oi->wsize = 384;
270 		break;
271 	case 7:		/* 16x64 *//* 1024 bits */
272 		oi->rows = 16;
273 		oi->cols = 64;
274 		oi->wsize = 64;
275 		break;
276 	default:
277 		/* Don't know the geometry */
278 		return -EBADE;
279 	}
280 
281 	/* Retrieve OTP region info */
282 	_ipxotp_init(oi);
283 	return 0;
284 }
285 
286 static int
ipxotp_read_region(struct otpinfo * oi,int region,u16 * data,uint * wlen)287 ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
288 {
289 	uint base, i, sz;
290 
291 	/* Validate region selection */
292 	switch (region) {
293 	case OTP_HW_RGN:
294 		sz = (uint) oi->hwlim - oi->hwbase;
295 		if (!(oi->status & OTPS_GUP_HW)) {
296 			*wlen = sz;
297 			return -ENODATA;
298 		}
299 		if (*wlen < sz) {
300 			*wlen = sz;
301 			return -EOVERFLOW;
302 		}
303 		base = oi->hwbase;
304 		break;
305 	case OTP_SW_RGN:
306 		sz = ((uint) oi->swlim - oi->swbase);
307 		if (!(oi->status & OTPS_GUP_SW)) {
308 			*wlen = sz;
309 			return -ENODATA;
310 		}
311 		if (*wlen < sz) {
312 			*wlen = sz;
313 			return -EOVERFLOW;
314 		}
315 		base = oi->swbase;
316 		break;
317 	case OTP_CI_RGN:
318 		sz = OTPGU_CI_SZ;
319 		if (!(oi->status & OTPS_GUP_CI)) {
320 			*wlen = sz;
321 			return -ENODATA;
322 		}
323 		if (*wlen < sz) {
324 			*wlen = sz;
325 			return -EOVERFLOW;
326 		}
327 		base = oi->otpgu_base + OTPGU_CI_OFF;
328 		break;
329 	case OTP_FUSE_RGN:
330 		sz = (uint) oi->flim - oi->fbase;
331 		if (!(oi->status & OTPS_GUP_FUSE)) {
332 			*wlen = sz;
333 			return -ENODATA;
334 		}
335 		if (*wlen < sz) {
336 			*wlen = sz;
337 			return -EOVERFLOW;
338 		}
339 		base = oi->fbase;
340 		break;
341 	case OTP_ALL_RGN:
342 		sz = ((uint) oi->flim - oi->hwbase);
343 		if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
344 			*wlen = sz;
345 			return -ENODATA;
346 		}
347 		if (*wlen < sz) {
348 			*wlen = sz;
349 			return -EOVERFLOW;
350 		}
351 		base = oi->hwbase;
352 		break;
353 	default:
354 		return -EINVAL;
355 	}
356 
357 	/* Read the data */
358 	for (i = 0; i < sz; i++)
359 		data[i] = ipxotp_otpr(oi, base + i);
360 
361 	*wlen = sz;
362 	return 0;
363 }
364 
365 static const struct otp_fn_s ipxotp_fn = {
366 	(int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init,
367 	(int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region,
368 };
369 
otp_init(struct si_pub * sih,struct otpinfo * oi)370 static int otp_init(struct si_pub *sih, struct otpinfo *oi)
371 {
372 	int ret;
373 
374 	memset(oi, 0, sizeof(struct otpinfo));
375 
376 	oi->core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
377 
378 	if (OTPTYPE_IPX(ai_get_ccrev(sih)))
379 		oi->fn = &ipxotp_fn;
380 
381 	if (oi->fn == NULL)
382 		return -EBADE;
383 
384 	oi->sih = sih;
385 
386 	ret = (oi->fn->init)(sih, oi);
387 
388 	return ret;
389 }
390 
391 int
otp_read_region(struct si_pub * sih,int region,u16 * data,uint * wlen)392 otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) {
393 	struct otpinfo otpinfo;
394 	struct otpinfo *oi = &otpinfo;
395 	int err = 0;
396 
397 	if (ai_is_otp_disabled(sih)) {
398 		err = -EPERM;
399 		goto out;
400 	}
401 
402 	err = otp_init(sih, oi);
403 	if (err)
404 		goto out;
405 
406 	err = ((oi)->fn->read_region)(oi, region, data, wlen);
407 
408  out:
409 	return err;
410 }
411