1/*
2 * OTP support.
3 *
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $Id: bcmotp.c,v 1.137.2.23 2011/02/01 06:16:34 Exp $
19 */
20
21#include <typedefs.h>
22#include <bcmdefs.h>
23#include <osl.h>
24#include <bcmdevs.h>
25#include <bcmutils.h>
26#include <siutils.h>
27#include <bcmendian.h>
28#include <hndsoc.h>
29#include <sbchipc.h>
30#include <bcmotp.h>
31
32/*
33 * There are two different OTP controllers so far:
34 * 	1. new IPX OTP controller:	chipc 21, >=23
35 * 	2. older HND OTP controller:	chipc 12, 17, 22
36 *
37 * Define BCMHNDOTP to include support for the HND OTP controller.
38 * Define BCMIPXOTP to include support for the IPX OTP controller.
39 *
40 * NOTE 1: More than one may be defined
41 * NOTE 2: If none are defined, the default is to include them all.
42 */
43
44#if !defined(BCMHNDOTP) && !defined(BCMIPXOTP)
45#define BCMHNDOTP	1
46#define BCMIPXOTP	1
47#endif
48
49#define OTPTYPE_HND(ccrev)	((ccrev) < 21 || (ccrev) == 22)
50#define OTPTYPE_IPX(ccrev)	((ccrev) == 21 || (ccrev) >= 23)
51
52#define OTP_ERR_VAL	0x0001
53#define OTP_MSG_VAL	0x0002
54#define OTP_DBG_VAL	0x0004
55uint32 otp_msg_level = OTP_ERR_VAL;
56
57#define OTP_ERR(args)
58
59#define OTP_MSG(args)
60#define OTP_DBG(args)
61
62#define OTPP_TRIES	10000000	/* # of tries for OTPP */
63
64#ifdef BCMIPXOTP
65#define MAXNUMRDES		9		/* Maximum OTP redundancy entries */
66#endif
67
68/* OTP common function type */
69typedef int	(*otp_status_t)(void *oh);
70typedef int	(*otp_size_t)(void *oh);
71typedef void*	(*otp_init_t)(si_t *sih);
72typedef uint16	(*otp_read_bit_t)(void *oh, chipcregs_t *cc, uint off);
73typedef int	(*otp_read_region_t)(si_t *sih, int region, uint16 *data, uint *wlen);
74typedef int	(*otp_nvread_t)(void *oh, char *data, uint *len);
75typedef int	(*otp_write_region_t)(void *oh, int region, uint16 *data, uint wlen);
76typedef int	(*otp_cis_append_region_t)(si_t *sih, int region, char *vars, int count);
77typedef int	(*otp_lock_t)(si_t *sih);
78typedef int	(*otp_nvwrite_t)(void *oh, uint16 *data, uint wlen);
79typedef int	(*otp_dump_t)(void *oh, int arg, char *buf, uint size);
80typedef int	(*otp_write_word_t)(void *oh, uint wn, uint16 data);
81typedef int	(*otp_read_word_t)(void *oh, uint wn, uint16 *data);
82
83/* OTP function struct */
84typedef struct otp_fn_s {
85	otp_size_t		size;
86	otp_read_bit_t		read_bit;
87
88	otp_init_t		init;
89	otp_read_region_t	read_region;
90	otp_nvread_t		nvread;
91#ifdef BCMNVRAMW
92	otp_write_region_t	write_region;
93	otp_cis_append_region_t	cis_append_region;
94	otp_lock_t		lock;
95	otp_nvwrite_t		nvwrite;
96#endif /* BCMNVRAMW */
97
98#if defined(WLTEST)
99	otp_dump_t		dump;
100#endif
101
102	otp_status_t		status;
103#ifdef BCMNVRAMW
104	otp_write_word_t	write_word;
105#endif /* BCMNVRAMW */
106	otp_read_word_t		read_word;
107} otp_fn_t;
108
109typedef struct {
110	uint		ccrev;		/* chipc revision */
111	otp_fn_t	*fn;		/* OTP functions */
112	si_t		*sih;		/* Saved sb handle */
113	osl_t		*osh;
114
115#ifdef BCMIPXOTP
116	/* IPX OTP section */
117	uint16		wsize;		/* Size of otp in words */
118	uint16		rows;		/* Geometry */
119	uint16		cols;		/* Geometry */
120	uint32		status;		/* Flag bits (lock/prog/rv).
121					 * (Reflected only when OTP is power cycled)
122					 */
123	uint16		hwbase;		/* hardware subregion offset */
124	uint16		hwlim;		/* hardware subregion boundary */
125	uint16		swbase;		/* software subregion offset */
126	uint16		swlim;		/* software subregion boundary */
127	uint16		fbase;		/* fuse subregion offset */
128	uint16		flim;		/* fuse subregion boundary */
129	int		otpgu_base;	/* offset to General Use Region */
130	uint16		fusebits;	/* num of fusebits */
131#ifdef BCMNVRAMW
132	struct {
133		uint8 width;		/* entry width in bits */
134		uint8 val_shift;	/* value bit offset in the entry */
135		uint8 offsets;		/* # entries */
136		uint8 stat_shift;	/* valid bit in otpstatus */
137		uint16 offset[MAXNUMRDES];	/* entry offset in OTP */
138	} rde_cb;			/* OTP redundancy control blocks */
139#endif /* BCMNVRAMW */
140#endif /* BCMIPXOTP */
141
142#ifdef BCMHNDOTP
143	/* HND OTP section */
144	uint		size;		/* Size of otp in bytes */
145	uint		hwprot;		/* Hardware protection bits */
146	uint		signvalid;	/* Signature valid bits */
147	int		boundary;	/* hw/sw boundary */
148#endif /* BCMHNDOTP */
149} otpinfo_t;
150
151static otpinfo_t otpinfo;
152
153/*
154 * IPX OTP Code
155 *
156 *   Exported functions:
157 *	ipxotp_status()
158 *	ipxotp_size()
159 *	ipxotp_init()
160 *	ipxotp_read_bit()
161 *	ipxotp_read_region()
162 *	ipxotp_read_word()
163 *	ipxotp_nvread()
164 *	ipxotp_write_region()
165 *	ipxotp_write_word()
166 *	ipxotp_cis_append_region()
167 *	ipxotp_lock()
168 *	ipxotp_nvwrite()
169 *	ipxotp_dump()
170 *
171 *   IPX internal functions:
172 *	ipxotp_otpr()
173 *	_ipxotp_init()
174 *	ipxotp_write_bit()
175 *	ipxotp_otpwb16()
176 *	ipxotp_write_rde()
177 *	ipxotp_fix_word16()
178 *	ipxotp_check_word16()
179 *	ipxotp_max_rgnsz()
180 *	ipxotp_otprb16()
181 *
182 */
183
184#ifdef BCMIPXOTP
185
186#define HWSW_RGN(rgn)		(((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
187
188/* OTP layout */
189/* CC revs 21, 24 and 27 OTP General Use Region word offset */
190#define REVA4_OTPGU_BASE	12
191
192/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
193#define REVB8_OTPGU_BASE	20
194
195/* CC rev 36 OTP General Use Region word offset */
196#define REV36_OTPGU_BASE	12
197
198/* Subregion word offsets in General Use region */
199#define OTPGU_HSB_OFF		0
200#define OTPGU_SFB_OFF		1
201#define OTPGU_CI_OFF		2
202#define OTPGU_P_OFF		3
203#define OTPGU_SROM_OFF		4
204
205/* Flag bit offsets in General Use region  */
206#define OTPGU_HWP_OFF		60
207#define OTPGU_SWP_OFF		61
208#define OTPGU_CIP_OFF		62
209#define OTPGU_FUSEP_OFF		63
210#define OTPGU_CIP_MSK		0x4000
211#define OTPGU_P_MSK		0xf000
212#define OTPGU_P_SHIFT		(OTPGU_HWP_OFF % 16)
213
214/* LOCK but offset */
215#define OTP_LOCK_ROW1_LOC_OFF	63	/* 1st ROW lock bit */
216#define OTP_LOCK_ROW2_LOC_OFF	127	/* 2nd ROW lock bit */
217#define OTP_LOCK_RD_LOC_OFF	128	/* Redundnancy Region lock bit */
218#define OTP_LOCK_GU_LOC_OFF	129	/* General User Region lock bit */
219
220
221/* OTP Size */
222#define OTP_SZ_FU_324		((ROUNDUP(324,8))/8)	/* 324 bits */
223#define OTP_SZ_FU_288		(288/8)		/* 288 bits */
224#define OTP_SZ_FU_216		(216/8)		/* 216 bits */
225#define OTP_SZ_FU_72		(72/8)		/* 72 bits */
226#define OTP_SZ_CHECKSUM		(16/8)		/* 16 bits */
227#define OTP4315_SWREG_SZ	178		/* 178 bytes */
228#define OTP_SZ_FU_144		(144/8)		/* 144 bits */
229#define OTP_SZ_FU_180		((ROUNDUP(180,8))/8)	/* 180 bits */
230
231static int
232ipxotp_status(void *oh)
233{
234	otpinfo_t *oi = (otpinfo_t *)oh;
235	return (int)(oi->status);
236}
237
238/* Return size in bytes */
239static int
240ipxotp_size(void *oh)
241{
242	otpinfo_t *oi = (otpinfo_t *)oh;
243	return (int)oi->wsize * 2;
244}
245
246static uint16
247ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
248{
249	otpinfo_t *oi;
250
251	oi = (otpinfo_t *)oh;
252
253	ASSERT(wn < oi->wsize);
254	ASSERT(cc != NULL);
255
256	return R_REG(oi->osh, &cc->sromotp[wn]);
257}
258
259static uint16
260ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
261{
262	otpinfo_t *oi = (otpinfo_t *)oh;
263	uint k, row, col;
264	uint32 otpp, st;
265
266	row = off / oi->cols;
267	col = off % oi->cols;
268
269	otpp = OTPP_START_BUSY |
270	        ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
271	        ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
272	        ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
273	OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x",
274	         __FUNCTION__, off, row, col, otpp));
275	W_REG(oi->osh, &cc->otpprog, otpp);
276
277	for (k = 0;
278	     ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
279	     k ++)
280		;
281	if (k >= OTPP_TRIES) {
282		OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
283		return 0xffff;
284	}
285	if (st & OTPP_READERR) {
286		OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, off));
287		return 0xffff;
288	}
289	st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
290
291	OTP_DBG((" => %d\n", st));
292	return (int)st;
293}
294
295
296/* Calculate max HW/SW region byte size by substracting fuse region and checksum size,
297 * osizew is oi->wsize (OTP size - GU size) in words
298 */
299static int
300ipxotp_max_rgnsz(otpinfo_t *oi)
301{
302	int osizew = oi->wsize;
303	int ret = 0;
304	uint16 checksum;
305	uint idx;
306	chipcregs_t *cc;
307
308	idx = si_coreidx(oi->sih);
309	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
310	ASSERT(cc != NULL);
311
312	checksum = OTP_SZ_CHECKSUM;
313
314	/* for new chips, fusebit is available from cc register */
315	if (oi->sih->ccrev >= 35) {
316		oi->fusebits = R_REG(oi->osh, &cc->otplayoutextension) & OTPLAYOUTEXT_FUSE_MASK;
317	}
318
319	si_setcoreidx(oi->sih, idx);
320
321	switch (CHIPID(oi->sih->chip)) {
322	case BCM4322_CHIP_ID:	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
323		oi->fusebits = OTP_SZ_FU_288;
324		break;
325	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
326	case BCM43224_CHIP_ID:	case BCM43225_CHIP_ID:	case BCM43421_CHIP_ID:
327	case BCM43226_CHIP_ID:  case BCM43420_CHIP_ID:
328		oi->fusebits = OTP_SZ_FU_72;
329		break;
330	case BCM43236_CHIP_ID:	case BCM43235_CHIP_ID:	case BCM43238_CHIP_ID:
331	case BCM43234_CHIP_ID:	case BCM43237_CHIP_ID:
332		oi->fusebits = OTP_SZ_FU_324;
333		break;
334	case BCM4325_CHIP_ID:
335	case BCM5356_CHIP_ID:
336		oi->fusebits = OTP_SZ_FU_216;
337		break;
338	case BCM4336_CHIP_ID:
339	case BCM43362_CHIP_ID:
340		oi->fusebits = OTP_SZ_FU_144;
341		break;
342	case BCM4313_CHIP_ID:
343		oi->fusebits = OTP_SZ_FU_72;
344		break;
345	case BCM4330_CHIP_ID:
346		oi->fusebits = OTP_SZ_FU_144;
347		break;
348	case BCM4319_CHIP_ID:
349		oi->fusebits = OTP_SZ_FU_180;
350		break;
351	case BCM4331_CHIP_ID:
352	case BCM43431_CHIP_ID:
353		oi->fusebits = OTP_SZ_FU_72;
354		break;
355	case BCM43228_CHIP_ID:
356	case BCM43428_CHIP_ID:
357		oi->fusebits = OTP_SZ_FU_72;
358		break;
359	case BCM43227_CHIP_ID:
360		oi->fusebits = OTP_SZ_FU_72;
361		break;
362	default:
363		ASSERT(0);	/* Don't konw about this chip */
364	}
365
366	ret = osizew*2 - oi->fusebits - checksum;
367
368	if (CHIPID(oi->sih->chip) == BCM4315_CHIP_ID) {
369		ret = OTP4315_SWREG_SZ;
370	}
371
372	OTP_MSG(("max region size %d bytes\n", ret));
373	return ret;
374}
375
376static void
377BCMNMIATTACHFN(_ipxotp_init)(otpinfo_t *oi, chipcregs_t *cc)
378{
379	uint	k;
380	uint32 otpp, st;
381
382	/* record word offset of General Use Region for various chipcommon revs */
383	if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 || oi->sih->ccrev == 27) {
384		oi->otpgu_base = REVA4_OTPGU_BASE;
385	} else if (oi->sih->ccrev == 36) {
386		/* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
387		if (oi->wsize >= 128)
388			oi->otpgu_base = REVB8_OTPGU_BASE;
389		else
390			oi->otpgu_base = REV36_OTPGU_BASE;
391	} else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
392		oi->otpgu_base = REVB8_OTPGU_BASE;
393	} else {
394		OTP_ERR(("%s: chipc rev %d not supported\n", __FUNCTION__, oi->sih->ccrev));
395	}
396
397	/* First issue an init command so the status is up to date */
398	otpp = OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
399
400	OTP_DBG(("%s: otpp = 0x%x", __FUNCTION__, otpp));
401	W_REG(oi->osh, &cc->otpprog, otpp);
402	for (k = 0;
403	     ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
404	     k ++)
405		;
406	if (k >= OTPP_TRIES) {
407		OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
408		return;
409	}
410
411	/* Read OTP lock bits and subregion programmed indication bits */
412	oi->status = R_REG(oi->osh, &cc->otpstatus);
413
414	if ((CHIPID(oi->sih->chip) == BCM43222_CHIP_ID) ||
415		(CHIPID(oi->sih->chip) == BCM43420_CHIP_ID) ||
416		(CHIPID(oi->sih->chip) == BCM43111_CHIP_ID) ||
417		(CHIPID(oi->sih->chip) == BCM43112_CHIP_ID) ||
418		(CHIPID(oi->sih->chip) == BCM43224_CHIP_ID) ||
419		(CHIPID(oi->sih->chip) == BCM43225_CHIP_ID) ||
420		(CHIPID(oi->sih->chip) == BCM43421_CHIP_ID) ||
421		(CHIPID(oi->sih->chip) == BCM43226_CHIP_ID) ||
422		(CHIPID(oi->sih->chip) == BCM43236_CHIP_ID) ||
423		(CHIPID(oi->sih->chip) == BCM43235_CHIP_ID) ||
424		(CHIPID(oi->sih->chip) == BCM43234_CHIP_ID) ||
425		(CHIPID(oi->sih->chip) == BCM43238_CHIP_ID) ||
426		(CHIPID(oi->sih->chip) == BCM43237_CHIP_ID) ||
427		(CHIPID(oi->sih->chip) == BCM4331_CHIP_ID) ||
428		(CHIPID(oi->sih->chip) == BCM43431_CHIP_ID) ||
429	0) {
430		uint32 p_bits;
431		p_bits = (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & OTPGU_P_MSK)
432			>> OTPGU_P_SHIFT;
433		oi->status |= (p_bits << OTPS_GUP_SHIFT);
434	}
435	OTP_DBG(("%s: status 0x%x\n", __FUNCTION__, oi->status));
436
437	/*
438	 * h/w region base and fuse region limit are fixed to the top and
439	 * the bottom of the general use region. Everything else can be flexible.
440	 */
441	oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
442	oi->hwlim = oi->wsize;
443	if (oi->status & OTPS_GUP_HW) {
444		OTP_DBG(("%s: hw region programmed\n", __FUNCTION__));
445		oi->hwlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
446		oi->swbase = oi->hwlim;
447	} else {
448		oi->hwlim = ipxotp_max_rgnsz(oi) / 2;
449		oi->swbase = oi->hwbase;
450	}
451
452	/* subtract fuse and checksum from beginning */
453	oi->swlim = ipxotp_max_rgnsz(oi) / 2;
454
455	if (oi->status & OTPS_GUP_SW) {
456		OTP_DBG(("%s: sw region programmed\n", __FUNCTION__));
457		oi->swlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
458		oi->fbase = oi->swlim;
459	}
460	else
461		oi->fbase = oi->swbase;
462
463	oi->flim = oi->wsize;
464
465	OTP_DBG(("%s: OTP limits---\n"
466		"hwbase %d/%d hwlim %d/%d\n"
467		"swbase %d/%d swlim %d/%d\n"
468		"fbase %d/%d flim %d/%d\n", __FUNCTION__,
469		oi->hwbase, oi->hwbase * 16, oi->hwlim, oi->hwlim * 16,
470		oi->swbase, oi->swbase * 16, oi->swlim, oi->swlim * 16,
471		oi->fbase, oi->fbase * 16, oi->flim, oi->flim * 16));
472}
473
474static void *
475BCMNMIATTACHFN(ipxotp_init)(si_t *sih)
476{
477	uint idx;
478	chipcregs_t *cc;
479	otpinfo_t *oi;
480
481	OTP_MSG(("%s: Use IPX OTP controller\n", __FUNCTION__));
482
483	/* Make sure we're running IPX OTP */
484	ASSERT(OTPTYPE_IPX(sih->ccrev));
485	if (!OTPTYPE_IPX(sih->ccrev))
486		return NULL;
487
488	/* Make sure OTP is not disabled */
489	if (si_is_otp_disabled(sih)) {
490		OTP_MSG(("%s: OTP is disabled\n", __FUNCTION__));
491#if !defined(WLTEST)
492		return NULL;
493#endif
494	}
495
496	/* Make sure OTP is powered up */
497	if (!si_is_otp_powered(sih)) {
498		OTP_ERR(("%s: OTP is powered down\n", __FUNCTION__));
499		return NULL;
500	}
501
502	oi = &otpinfo;
503
504	/* Check for otp size */
505	switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
506	case 0:
507		/* Nothing there */
508		OTP_ERR(("%s: no OTP\n", __FUNCTION__));
509		return NULL;
510	case 1:	/* 32x64 */
511		oi->rows = 32;
512		oi->cols = 64;
513		oi->wsize = 128;
514		break;
515	case 2:	/* 64x64 */
516		oi->rows = 64;
517		oi->cols = 64;
518		oi->wsize = 256;
519		break;
520	case 5:	/* 96x64 */
521		oi->rows = 96;
522		oi->cols = 64;
523		oi->wsize = 384;
524		break;
525	case 7:	/* 16x64 */ /* 1024 bits */
526		oi->rows = 16;
527		oi->cols = 64;
528		oi->wsize = 64;
529		break;
530	default:
531		/* Don't know the geometry */
532		OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__));
533		return NULL;
534	}
535
536	OTP_MSG(("%s: rows %u cols %u wsize %u\n", __FUNCTION__, oi->rows, oi->cols, oi->wsize));
537
538#ifdef BCMNVRAMW
539	/* Initialize OTP redundancy control blocks */
540	if (sih->ccrev == 21 || sih->ccrev == 24) {
541		uint16 offset[] = {64, 79, 94, 109, 128, 143, 158, 173};
542		bcopy(offset, &oi->rde_cb.offset, sizeof(offset));
543		oi->rde_cb.offsets = ARRAYSIZE(offset);
544		oi->rde_cb.width = 15;
545		oi->rde_cb.val_shift = 11;
546		oi->rde_cb.stat_shift = 16;
547	}
548	else if (sih->ccrev == 27) {
549		uint16 offset[] = {128, 143, 158, 173};
550		bcopy(offset, &oi->rde_cb.offset, sizeof(offset));
551		oi->rde_cb.offsets = ARRAYSIZE(offset);
552		oi->rde_cb.width = 15;
553		oi->rde_cb.val_shift = 11;
554		oi->rde_cb.stat_shift = 20;
555	}
556	else {
557		uint16 offset[] = {141, 158, 175, 205, 222, 239, 269, 286, 303};
558		bcopy(offset, &oi->rde_cb.offset, sizeof(offset));
559		oi->rde_cb.offsets = ARRAYSIZE(offset);
560		oi->rde_cb.width = 17;
561		oi->rde_cb.val_shift = 13;
562		oi->rde_cb.stat_shift = 16;
563	}
564	ASSERT(oi->rde_cb.offsets <= MAXNUMRDES);
565#endif	/* BCMNVRAMW */
566
567	/* Retrieve OTP region info */
568	idx = si_coreidx(sih);
569	cc = si_setcoreidx(sih, SI_CC_IDX);
570	ASSERT(cc != NULL);
571
572	_ipxotp_init(oi, cc);
573
574	si_setcoreidx(sih, idx);
575
576	return (void *)oi;
577}
578
579static int
580ipxotp_read_region(void *oh, int region, uint16 *data, uint *wlen)
581{
582	otpinfo_t *oi = (otpinfo_t *)oh;
583	uint idx;
584	chipcregs_t *cc;
585	uint base, i, sz;
586
587	/* Validate region selection */
588	switch (region) {
589	case OTP_HW_RGN:
590		sz = (uint)oi->hwlim - oi->hwbase;
591		if (!(oi->status & OTPS_GUP_HW)) {
592			OTP_ERR(("%s: h/w region not programmed\n", __FUNCTION__));
593			*wlen = sz;
594			return BCME_NOTFOUND;
595		}
596		if (*wlen < sz) {
597			OTP_ERR(("%s: buffer too small, should be at least %u\n",
598			         __FUNCTION__, oi->hwlim - oi->hwbase));
599			*wlen = sz;
600			return BCME_BUFTOOSHORT;
601		}
602		base = oi->hwbase;
603		break;
604	case OTP_SW_RGN:
605		sz = ((uint)oi->swlim - oi->swbase);
606		if (!(oi->status & OTPS_GUP_SW)) {
607			OTP_ERR(("%s: s/w region not programmed\n", __FUNCTION__));
608			*wlen = sz;
609			return BCME_NOTFOUND;
610		}
611		if (*wlen < sz) {
612			OTP_ERR(("%s: buffer too small should be at least %u\n",
613			         __FUNCTION__, oi->swlim - oi->swbase));
614			*wlen = sz;
615			return BCME_BUFTOOSHORT;
616		}
617		base = oi->swbase;
618		break;
619	case OTP_CI_RGN:
620		sz = OTPGU_CI_SZ;
621		if (!(oi->status & OTPS_GUP_CI)) {
622			OTP_ERR(("%s: chipid region not programmed\n", __FUNCTION__));
623			*wlen = sz;
624			return BCME_NOTFOUND;
625		}
626		if (*wlen < sz) {
627			OTP_ERR(("%s: buffer too small, should be at least %u\n",
628			         __FUNCTION__, OTPGU_CI_SZ));
629			*wlen = sz;
630			return BCME_BUFTOOSHORT;
631		}
632		base = oi->otpgu_base + OTPGU_CI_OFF;
633		break;
634	case OTP_FUSE_RGN:
635		sz = (uint)oi->flim - oi->fbase;
636		if (!(oi->status & OTPS_GUP_FUSE)) {
637			OTP_ERR(("%s: fuse region not programmed\n", __FUNCTION__));
638			*wlen = sz;
639			return BCME_NOTFOUND;
640		}
641		if (*wlen < sz) {
642			OTP_ERR(("%s: buffer too small, should be at least %u\n",
643			         __FUNCTION__, oi->flim - oi->fbase));
644			*wlen = sz;
645			return BCME_BUFTOOSHORT;
646		}
647		base = oi->fbase;
648		break;
649	case OTP_ALL_RGN:
650		sz = ((uint)oi->flim - oi->hwbase);
651		if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
652			OTP_ERR(("%s: h/w & s/w region not programmed\n", __FUNCTION__));
653			*wlen = sz;
654			return BCME_NOTFOUND;
655		}
656		if (*wlen < sz) {
657			OTP_ERR(("%s: buffer too small, should be at least %u\n",
658				__FUNCTION__, oi->hwlim - oi->hwbase));
659			*wlen = sz;
660			return BCME_BUFTOOSHORT;
661		}
662		base = oi->hwbase;
663		break;
664	default:
665		OTP_ERR(("%s: reading region %d is not supported\n", __FUNCTION__, region));
666		return BCME_BADARG;
667	}
668
669	idx = si_coreidx(oi->sih);
670	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
671	ASSERT(cc != NULL);
672
673	/* Read the data */
674	for (i = 0; i < sz; i ++)
675		data[i] = ipxotp_otpr(oh, cc, base + i);
676
677	si_setcoreidx(oi->sih, idx);
678	*wlen = sz;
679	return 0;
680}
681
682static int
683ipxotp_read_word(void *oh, uint wn, uint16 *data)
684{
685	otpinfo_t *oi = (otpinfo_t *)oh;
686	uint idx;
687	chipcregs_t *cc;
688
689	idx = si_coreidx(oi->sih);
690	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
691	ASSERT(cc != NULL);
692
693	/* Read the data */
694	*data = ipxotp_otpr(oh, cc, wn);
695
696	si_setcoreidx(oi->sih, idx);
697	return 0;
698}
699
700static int
701ipxotp_nvread(void *oh, char *data, uint *len)
702{
703	return BCME_UNSUPPORTED;
704}
705
706#ifdef BCMNVRAMW
707static int
708ipxotp_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off)
709{
710	uint k, row, col;
711	uint32 otpp, st;
712
713	row = off / oi->cols;
714	col = off % oi->cols;
715
716	otpp = OTPP_START_BUSY |
717	        ((1 << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) |
718	        ((OTPPOC_BIT_PROG << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
719	        ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
720	        ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
721	OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n",
722	         __FUNCTION__, off, row, col, otpp));
723
724	W_REG(oi->osh, &cc->otpprog, otpp);
725
726	for (k = 0;
727	     ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
728	     k ++)
729		;
730	if (k >= OTPP_TRIES) {
731		OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
732		return -1;
733	}
734
735	return 0;
736}
737
738
739static int
740ipxotp_write_lock_bit(otpinfo_t *oi, chipcregs_t *cc, uint off)
741{
742	uint k, row, col;
743	uint32 otpp, st;
744
745	row = off / oi->cols;
746	col = off % oi->cols;
747
748	otpp = OTPP_START_BUSY |
749	        ((OTPPOC_ROW_LOCK << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
750	        ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
751	        ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
752	OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n",
753	         __FUNCTION__, off, row, col, otpp));
754
755	W_REG(oi->osh, &cc->otpprog, otpp);
756
757	for (k = 0;
758	     ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
759	     k ++)
760		;
761	if (k >= OTPP_TRIES) {
762		OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
763		return -1;
764	}
765
766	return 0;
767}
768
769static int
770ipxotp_otpwb16(otpinfo_t *oi, chipcregs_t *cc, int wn, uint16 data)
771{
772	uint base, i;
773	int rc = 0;
774
775	base = wn * 16;
776	for (i = 0; i < 16; i++) {
777		if (data & (1 << i)) {
778			if ((rc = ipxotp_write_bit(oi, cc, base + i)))
779				break;
780		}
781	}
782
783	return rc;
784}
785
786/* Write OTP redundancy entry:
787 *  rde - redundancy entry index (-ve for "next")
788 *  bit - bit offset
789 *  val - bit value
790 */
791int
792ipxotp_write_rde(void *oh, int rde, uint bit, uint val)
793{
794	otpinfo_t *oi = (otpinfo_t *)oh;
795	uint idx;
796	chipcregs_t *cc;
797	uint i, temp;
798
799#ifdef BCMCBG
800	if ((rde >= oi->rde_cb.offsets) || (bit >= oi->rows * oi->cols) || (val > 1))
801		return BCME_RANGE;
802#endif
803
804	if (rde < 0) {
805		for (rde = 0; rde < oi->rde_cb.offsets - 1; rde++) {
806			if ((oi->status & (1 << (oi->rde_cb.stat_shift + rde))) == 0)
807				break;
808		}
809		OTP_MSG(("%s: Auto rde index %d\n", __FUNCTION__, rde));
810	}
811
812	if (oi->status & (1 << (oi->rde_cb.stat_shift + rde))) {
813		OTP_MSG(("%s: rde %d already in use, status 0x%08x\n", __FUNCTION__,
814		         rde, oi->status));
815		return BCME_ERROR;
816	}
817
818	idx = si_coreidx(oi->sih);
819	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
820	ASSERT(cc != NULL);
821
822	temp = ~(~0 << oi->rde_cb.width) &
823	        ((~0 << (oi->rde_cb.val_shift + 1)) | (val << oi->rde_cb.val_shift) | bit);
824
825	OTP_MSG(("%s: rde %d bit %d val %d bmp 0x%08x\n", __FUNCTION__, rde, bit, val, temp));
826
827	/* Enable Write */
828	OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
829
830	for (i = 0; i < oi->rde_cb.width; i ++) {
831		if (!(temp & (1 << i)))
832			continue;
833		ipxotp_write_bit(oi, cc, oi->rde_cb.offset[rde] + i);
834	}
835
836	/* Disable Write */
837	AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
838
839	si_otp_power(oi->sih, FALSE);
840	si_otp_power(oi->sih, TRUE);
841	_ipxotp_init(oi, cc);
842
843	si_setcoreidx(oi->sih, idx);
844	return BCME_OK;
845}
846
847/* Set up redundancy entries for the specified bits */
848static int
849ipxotp_fix_word16(void *oh, uint wn, uint16 mask, uint16 val)
850{
851	otpinfo_t *oi;
852	uint bit;
853	int rc = 0;
854
855	oi = (otpinfo_t *)oh;
856
857	ASSERT(oi != NULL);
858	ASSERT(wn < oi->wsize);
859
860	for (bit = wn * 16; mask; bit++, mask >>= 1, val >>= 1) {
861		if (mask & 1) {
862			if ((rc = ipxotp_write_rde(oi, -1, bit, val & 1)))
863				break;
864		}
865	}
866
867	return rc;
868}
869
870static int
871ipxotp_check_word16(void *oh, chipcregs_t *cc, uint wn, uint16 val)
872{
873	otpinfo_t *oi = (otpinfo_t *)oh;
874	uint16 word = ipxotp_otpr(oi, cc, wn);
875	int rc = 0;
876
877	if ((word ^= val)) {
878		OTP_MSG(("%s: word %d is 0x%04x, wanted 0x%04x, fixing...\n",
879			__FUNCTION__, wn, (word ^ val), val));
880		if ((rc = ipxotp_fix_word16(oi, wn, word, val))) {
881			OTP_ERR(("FAILED, ipxotp_fix_word16 returns %d\n", rc));
882			/* Fatal error, unfixable. MFGC will have to fail. Board
883			 * needs to be discarded!!
884			 */
885			return BCME_NORESOURCE;
886		}
887	}
888
889	return BCME_OK;
890}
891
892/* expects the caller to disable interrupts before calling this routine */
893static int
894ipxotp_write_region(void *oh, int region, uint16 *data, uint wlen)
895{
896	otpinfo_t *oi = (otpinfo_t *)oh;
897	uint idx;
898	chipcregs_t *cc;
899	uint base, i;
900	int otpgu_bit_base;
901	bool rewrite = FALSE;
902	int rc = 0;
903	uint16 *origdata = NULL;
904
905	otpgu_bit_base = oi->otpgu_base * 16;
906
907	/* Validate region selection */
908	switch (region) {
909	case OTP_HW_RGN:
910		if (wlen > (uint)(oi->hwlim - oi->hwbase)) {
911			OTP_ERR(("%s: wlen %u exceeds OTP h/w region limit %u\n",
912			         __FUNCTION__, wlen, oi->hwlim - oi->hwbase));
913			return BCME_BUFTOOLONG;
914		}
915		rewrite = !!(oi->status & OTPS_GUP_HW);
916		base = oi->hwbase;
917		break;
918	case OTP_SW_RGN:
919		if (wlen > (uint)(oi->swlim - oi->swbase)) {
920			OTP_ERR(("%s: wlen %u exceeds OTP s/w region limit %u\n",
921			         __FUNCTION__, wlen, oi->swlim - oi->swbase));
922			return BCME_BUFTOOLONG;
923		}
924		rewrite = !!(oi->status & OTPS_GUP_SW);
925		base = oi->swbase;
926		break;
927	case OTP_CI_RGN:
928		if (oi->status & OTPS_GUP_CI) {
929			OTP_ERR(("%s: chipid region has been programmed\n", __FUNCTION__));
930			return BCME_ERROR;
931		}
932		if (wlen > OTPGU_CI_SZ) {
933			OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n",
934			         __FUNCTION__, wlen, OTPGU_CI_SZ));
935			return BCME_BUFTOOLONG;
936		}
937		if ((wlen == OTPGU_CI_SZ) && (data[OTPGU_CI_SZ - 1] & OTPGU_P_MSK) != 0) {
938			OTP_ERR(("%s: subregion programmed bits not zero\n", __FUNCTION__));
939			return BCME_BADARG;
940		}
941		base = oi->otpgu_base + OTPGU_CI_OFF;
942		break;
943	case OTP_FUSE_RGN:
944		if (oi->status & OTPS_GUP_FUSE) {
945			OTP_ERR(("%s: fuse region has been programmed\n", __FUNCTION__));
946			return BCME_ERROR;
947		}
948		if (wlen > (uint)(oi->flim - oi->fbase)) {
949			OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n",
950			         __FUNCTION__, wlen, oi->flim - oi->fbase));
951			return BCME_BUFTOOLONG;
952		}
953		base = oi->flim - wlen;
954		break;
955	default:
956		OTP_ERR(("%s: writing region %d is not supported\n", __FUNCTION__, region));
957		return BCME_ERROR;
958	}
959
960	idx = si_coreidx(oi->sih);
961	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
962	ASSERT(cc != NULL);
963
964	/* Check for conflict; Since some bits might be programmed at ATE time, we need to
965	 * avoid redundancy by clearing already written bits, but copy original for verification.
966	 */
967	if ((origdata = (uint16*)MALLOC(oi->osh, wlen * 2)) == NULL) {
968		rc = BCME_NOMEM;
969		goto exit;
970	}
971	for (i = 0; i < wlen; i++) {
972		origdata[i] = data[i];
973		data[i] = ipxotp_otpr(oi, cc, base + i);
974		if (data[i] & ~origdata[i]) {
975			OTP_ERR(("%s: %s region: word %d incompatible (0x%04x->0x%04x)\n",
976				__FUNCTION__, HWSW_RGN(region), i, data[i], origdata[i]));
977			rc = BCME_BADARG;
978			goto exit;
979		}
980		data[i] ^= origdata[i];
981	}
982	OTP_MSG(("%s: writing new bits in %s region\n", __FUNCTION__, HWSW_RGN(region)));
983
984	/* Enable Write */
985	OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
986
987	/* Write the data */
988	for (i = 0; i < wlen; i++) {
989		ipxotp_otpwb16(oi, cc, base + i, data[i]);
990	}
991
992	/* One time set region flag: Update boundary/flag in memory and in OTP */
993	if (!rewrite) {
994		switch (region) {
995		case OTP_HW_RGN:
996			ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, (base + i) * 16);
997			ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_HWP_OFF);
998			break;
999		case OTP_SW_RGN:
1000			/* Write HW region limit as well */
1001			ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, base * 16);
1002			/* write max swlim(covert to bits) to the sw/fuse boundary */
1003			ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, oi->swlim * 16);
1004			ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_SWP_OFF);
1005			break;
1006		case OTP_CI_RGN:
1007			ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_CIP_OFF);
1008			/* Also set the OTPGU_CIP_MSK bit in the input so verification
1009			 * doesn't fail
1010			 */
1011			if (wlen >= OTPGU_CI_SZ)
1012				data[OTPGU_CI_SZ - 1] |= OTPGU_CIP_MSK;
1013			break;
1014		case OTP_FUSE_RGN:
1015			ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, base * 16);
1016			ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_FUSEP_OFF);
1017			break;
1018		}
1019	}
1020
1021	/* Disable Write */
1022	AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
1023
1024	/* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */
1025	si_otp_power(oi->sih, FALSE);
1026	si_otp_power(oi->sih, TRUE);
1027
1028	/* Check and fix for region size and region programmed bits */
1029	if (!rewrite) {
1030		uint16	boundary_off = 0, boundary_val = 0;
1031		uint16	programmed_off = 0;
1032		uint16	bit = 0;
1033
1034		switch (region) {
1035		case OTP_HW_RGN:
1036			boundary_off = OTPGU_HSB_OFF;
1037			boundary_val = (base + i) * 16;
1038			programmed_off = OTPGU_HWP_OFF;
1039			break;
1040		case OTP_SW_RGN:
1041			/* Also write 0 to HW region boundary */
1042			if ((rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF,
1043				base * 16)))
1044				goto exit;
1045			boundary_off = OTPGU_SFB_OFF;
1046			boundary_val = oi->swlim * 16;
1047			programmed_off = OTPGU_SWP_OFF;
1048			break;
1049		case OTP_CI_RGN:
1050			/* No CI region boundary */
1051			programmed_off = OTPGU_CIP_OFF;
1052			break;
1053		case OTP_FUSE_RGN:
1054			boundary_off = OTPGU_SFB_OFF;
1055			boundary_val = base * 16;
1056			programmed_off = OTPGU_FUSEP_OFF;
1057			break;
1058		}
1059
1060		/* Do the actual checking and return BCME_NORESOURCE if we cannot fix */
1061		if ((region != OTP_CI_RGN) &&
1062			(rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + boundary_off,
1063			boundary_val))) {
1064			goto exit;
1065		}
1066
1067		if ((bit = ipxotp_read_bit(oh, cc, otpgu_bit_base + programmed_off)) == 0xffff) {
1068			OTP_ERR(("\n%s: FAILED bit %d reads %d\n", __FUNCTION__, otpgu_bit_base +
1069				programmed_off, bit));
1070			goto exit;
1071		} else if (bit == 0) {	/* error detected, fix it */
1072			OTP_ERR(("\n%s: FAILED bit %d reads %d, fixing\n", __FUNCTION__,
1073				otpgu_bit_base + programmed_off, bit));
1074			if ((rc = ipxotp_write_rde(oi, -1, otpgu_bit_base + programmed_off, 1))) {
1075				OTP_ERR(("\n%s: cannot fix, ipxotp_write_rde returns %d\n",
1076					__FUNCTION__, rc));
1077				goto exit;
1078			}
1079		}
1080	}
1081
1082	/* Update status, apply WAR */
1083	_ipxotp_init(oi, cc);
1084
1085	/* Recover original data... */
1086	if (origdata)
1087		bcopy(origdata, data, wlen * 2);
1088
1089	/* ...so we can verify and fix where possible */
1090	for (i = 0; i < wlen; i++) {
1091		if ((rc = ipxotp_check_word16(oi, cc, base + i, data[i])))
1092			goto exit;
1093	}
1094
1095exit:
1096	if (origdata)
1097		MFREE(oi->osh, origdata, wlen * 2);
1098
1099	si_setcoreidx(oi->sih, idx);
1100	return rc;
1101}
1102
1103static int
1104ipxotp_write_word(void *oh, uint wn, uint16 data)
1105{
1106	otpinfo_t *oi = (otpinfo_t *)oh;
1107	int rc = 0;
1108	uint16 origdata;
1109	uint idx;
1110	chipcregs_t *cc;
1111
1112	idx = si_coreidx(oi->sih);
1113	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1114	ASSERT(cc != NULL);
1115
1116	/* Check for conflict */
1117	origdata = data;
1118	data = ipxotp_otpr(oi, cc, wn);
1119	if (data & ~origdata) {
1120		OTP_ERR(("%s: word %d incompatible (0x%04x->0x%04x)\n",
1121			__FUNCTION__, wn, data, origdata));
1122		rc = BCME_BADARG;
1123		goto exit;
1124	}
1125	data ^= origdata;
1126
1127	/* Enable Write */
1128	OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
1129
1130	rc = ipxotp_otpwb16(oi, cc, wn, data);
1131
1132	/* Disable Write */
1133	AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
1134
1135	data = origdata;
1136	if ((rc = ipxotp_check_word16(oi, cc, wn, data)))
1137		goto exit;
1138exit:
1139	si_setcoreidx(oi->sih, idx);
1140	return rc;
1141}
1142
1143static int
1144ipxotp_cis_append_region(si_t *sih, int region, char *vars, int count)
1145{
1146	uint8 *cis;
1147	osl_t *osh;
1148	uint sz = OTP_SZ_MAX/2; /* size in words */
1149	int rc = 0;
1150	bool newchip = FALSE;
1151
1152	ASSERT(region == OTP_HW_RGN || region == OTP_SW_RGN);
1153
1154	osh = si_osh(sih);
1155	if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) {
1156		return BCME_ERROR;
1157	}
1158
1159	bzero(cis, OTP_SZ_MAX);
1160
1161	rc = otp_read_region(sih, region, (uint16 *)cis, &sz);
1162	newchip = (rc == BCME_NOTFOUND) ? TRUE : FALSE;
1163	if ((rc != 0) && (rc != BCME_NOTFOUND)) {
1164		return BCME_ERROR;
1165	}
1166	rc = 0;
1167
1168	/* zero count for read, non-zero count for write */
1169	if (count) {
1170		int i = 0, newlen = 0;
1171
1172		if (newchip) {
1173			int termw_len = 0;	/* length of termination word */
1174
1175			/* convert halfwords to bytes offset */
1176			newlen = sz * 2;
1177
1178			if ((CHIPID(sih->chip) == BCM4322_CHIP_ID) ||
1179				(CHIPID(sih->chip) == BCM43231_CHIP_ID) ||
1180				(CHIPID(sih->chip) == BCM4315_CHIP_ID) ||
1181				(CHIPID(sih->chip) == BCM4319_CHIP_ID)) {
1182				/* bootloader WAR, refer to above twiki link */
1183				cis[newlen-1] = 0x00;
1184				cis[newlen-2] = 0xff;
1185				cis[newlen-3] = 0x00;
1186				cis[newlen-4] = 0xff;
1187				cis[newlen-5] = 0xff;
1188				cis[newlen-6] = 0x1;
1189				cis[newlen-7] = 0x2;
1190				termw_len = 7;
1191			} else {
1192				cis[newlen-1] = 0xff;
1193				cis[newlen-2] = 0xff;
1194				termw_len = 2;
1195			}
1196
1197			if (count >= newlen - termw_len) {
1198				OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", newlen, count));
1199				rc = BCME_BUFTOOLONG;
1200			}
1201		} else {
1202			int end = 0;
1203
1204			/* Walk through the leading zeros (could be 0 or 8 bytes for now) */
1205			for (i = 0; i < (int)sz*2; i++)
1206				if (cis[i] != 0)
1207					break;
1208
1209			/* Find the place to append */
1210			for (; i < (int)sz*2; i++) {
1211				if (cis[i] == 0)
1212					break;
1213				i += ((int)cis[i+1] + 1);
1214			}
1215
1216			for (end = i; end < (int)sz*2; end++) {
1217				if (cis[end] != 0)
1218					break;
1219			}
1220
1221			newlen = i + count;
1222			if (newlen & 1)		/* make it even-sized buffer */
1223				newlen++;
1224
1225			if (newlen >= (end - 1)) {
1226				OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", end-i, count));
1227				rc = BCME_BUFTOOLONG;
1228			}
1229		}
1230
1231		/* copy the buffer */
1232		memcpy(&cis[i], vars, count);
1233#ifdef BCMNVRAMW
1234		/* Write the buffer back */
1235		if (!rc)
1236			rc = otp_write_region(sih, region, (uint16*)cis, newlen/2);
1237
1238		/* Print the buffer */
1239		OTP_MSG(("Buffer of size %d bytes to write:\n", newlen));
1240		for (i = 0; i < newlen; i++) {
1241			OTP_DBG(("%02x ", cis[i] & 0xff));
1242			if ((i % 16) == 15) {
1243				OTP_DBG(("\n"));
1244			}
1245		}
1246		OTP_MSG(("\n"));
1247#endif /* BCMNVRAMW */
1248	}
1249
1250	if (cis)
1251		MFREE(osh, cis, OTP_SZ_MAX);
1252
1253	return (rc);
1254}
1255
1256/* No need to lock for IPXOTP */
1257static int
1258ipxotp_lock(void *oh)
1259{
1260	uint idx;
1261	chipcregs_t *cc;
1262	otpinfo_t *oi = (otpinfo_t *)oh;
1263	int err = 0, rc = 0;
1264
1265	idx = si_coreidx(oi->sih);
1266	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1267	ASSERT(cc != NULL);
1268
1269	/* Enable Write */
1270	OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
1271
1272	err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW1_LOC_OFF);
1273	if (err) {
1274		OTP_ERR(("fail to lock ROW1\n"));
1275		rc = -1;
1276	}
1277	err =  ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW2_LOC_OFF);
1278	if (err) {
1279		OTP_ERR(("fail to lock ROW2\n"));
1280		rc = -2;
1281	}
1282	err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_RD_LOC_OFF);
1283	if (err) {
1284		OTP_ERR(("fail to lock RD\n"));
1285		rc = -3;
1286	}
1287	err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_GU_LOC_OFF);
1288	if (err) {
1289		OTP_ERR(("fail to lock GU\n"));
1290		rc = -4;
1291	}
1292
1293	/* Disable Write */
1294	AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
1295
1296	/* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */
1297	si_otp_power(oi->sih, FALSE);
1298	si_otp_power(oi->sih, TRUE);
1299
1300	/* Update status, apply WAR */
1301	_ipxotp_init(oi, cc);
1302	return rc;
1303}
1304
1305static int
1306ipxotp_nvwrite(void *oh, uint16 *data, uint wlen)
1307{
1308	return -1;
1309}
1310#endif /* BCMNVRAMW */
1311
1312#if defined(WLTEST)
1313static uint16
1314ipxotp_otprb16(void *oh, chipcregs_t *cc, uint wn)
1315{
1316	uint base, i;
1317	uint16 val;
1318	uint16 bit;
1319
1320	base = wn * 16;
1321
1322	val = 0;
1323	for (i = 0; i < 16; i++) {
1324		if ((bit = ipxotp_read_bit(oh, cc, base + i)) == 0xffff)
1325			break;
1326		val = val | (bit << i);
1327	}
1328	if (i < 16)
1329		val = 0xffff;
1330
1331	return val;
1332}
1333
1334static int
1335ipxotp_dump(void *oh, int arg, char *buf, uint size)
1336{
1337	otpinfo_t *oi = (otpinfo_t *)oh;
1338	chipcregs_t *cc;
1339	uint idx, i, count;
1340	uint16 val;
1341	struct bcmstrbuf b;
1342
1343	idx = si_coreidx(oi->sih);
1344	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1345	ASSERT(cc != NULL);
1346
1347	count = ipxotp_size(oh);
1348
1349	bcm_binit(&b, buf, size);
1350	for (i = 0; i < count / 2; i++) {
1351		if (!(i % 4))
1352			bcm_bprintf(&b, "\n0x%04x:", 2 * i);
1353		if (arg == 0)
1354			val = ipxotp_otpr(oh, cc, i);
1355		else
1356			val = ipxotp_otprb16(oi, cc, i);
1357		bcm_bprintf(&b, " 0x%04x", val);
1358	}
1359	bcm_bprintf(&b, "\n");
1360
1361	si_setcoreidx(oi->sih, idx);
1362
1363	return ((int)(b.buf - b.origbuf));
1364}
1365#endif
1366
1367static otp_fn_t ipxotp_fn = {
1368	(otp_size_t)ipxotp_size,
1369	(otp_read_bit_t)ipxotp_read_bit,
1370
1371	(otp_init_t)ipxotp_init,
1372	(otp_read_region_t)ipxotp_read_region,
1373	(otp_nvread_t)ipxotp_nvread,
1374#ifdef BCMNVRAMW
1375	(otp_write_region_t)ipxotp_write_region,
1376	(otp_cis_append_region_t)ipxotp_cis_append_region,
1377	(otp_lock_t)ipxotp_lock,
1378	(otp_nvwrite_t)ipxotp_nvwrite,
1379#endif /* BCMNVRAMW */
1380
1381#if defined(WLTEST)
1382	(otp_dump_t)ipxotp_dump,
1383#endif
1384
1385	(otp_status_t)ipxotp_status,
1386#ifdef BCMNVRAMW
1387	(otp_write_word_t)ipxotp_write_word,
1388#endif /* BCMNVRAMW */
1389	(otp_read_word_t)ipxotp_read_word,
1390};
1391
1392#endif /* BCMIPXOTP */
1393
1394
1395/*
1396 * HND OTP Code
1397 *
1398 *   Exported functions:
1399 *	hndotp_status()
1400 *	hndotp_size()
1401 *	hndotp_init()
1402 *	hndotp_read_bit()
1403 *	hndotp_read_region()
1404 *	hndotp_read_word()
1405 *	hndotp_nvread()
1406 *	hndotp_write_region()
1407 *	hndotp_cis_append_region()
1408 *	hndotp_lock()
1409 *	hndotp_nvwrite()
1410 *	hndotp_dump()
1411 *
1412 *   HND internal functions:
1413 * 	hndotp_otpr()
1414 * 	hndotp_otproff()
1415 *	hndotp_write_bit()
1416 *	hndotp_write_word()
1417 *	hndotp_valid_rce()
1418 *	hndotp_write_rce()
1419 *	hndotp_write_row()
1420 *	hndotp_otprb16()
1421 *
1422 */
1423
1424#ifdef BCMHNDOTP
1425
1426/* Fields in otpstatus */
1427#define	OTPS_PROGFAIL		0x80000000
1428#define	OTPS_PROTECT		0x00000007
1429#define	OTPS_HW_PROTECT		0x00000001
1430#define	OTPS_SW_PROTECT		0x00000002
1431#define	OTPS_CID_PROTECT	0x00000004
1432#define	OTPS_RCEV_MSK		0x00003f00
1433#define	OTPS_RCEV_SHIFT		8
1434
1435/* Fields in the otpcontrol register */
1436#define	OTPC_RECWAIT		0xff000000
1437#define	OTPC_PROGWAIT		0x00ffff00
1438#define	OTPC_PRW_SHIFT		8
1439#define	OTPC_MAXFAIL		0x00000038
1440#define	OTPC_VSEL		0x00000006
1441#define	OTPC_SELVL		0x00000001
1442
1443/* OTP regions (Word offsets from otp size) */
1444#define	OTP_SWLIM_OFF	(-4)
1445#define	OTP_CIDBASE_OFF	0
1446#define	OTP_CIDLIM_OFF	4
1447
1448/* Predefined OTP words (Word offset from otp size) */
1449#define	OTP_BOUNDARY_OFF (-4)
1450#define	OTP_HWSIGN_OFF	(-3)
1451#define	OTP_SWSIGN_OFF	(-2)
1452#define	OTP_CIDSIGN_OFF	(-1)
1453#define	OTP_CID_OFF	0
1454#define	OTP_PKG_OFF	1
1455#define	OTP_FID_OFF	2
1456#define	OTP_RSV_OFF	3
1457#define	OTP_LIM_OFF	4
1458#define	OTP_RD_OFF	4	/* Redundancy row starts here */
1459#define	OTP_RC0_OFF	28	/* Redundancy control word 1 */
1460#define	OTP_RC1_OFF	32	/* Redundancy control word 2 */
1461#define	OTP_RC_LIM_OFF	36	/* Redundancy control word end */
1462
1463#define	OTP_HW_REGION	OTPS_HW_PROTECT
1464#define	OTP_SW_REGION	OTPS_SW_PROTECT
1465#define	OTP_CID_REGION	OTPS_CID_PROTECT
1466
1467#if OTP_HW_REGION != OTP_HW_RGN
1468#error "incompatible OTP_HW_RGN"
1469#endif
1470#if OTP_SW_REGION != OTP_SW_RGN
1471#error "incompatible OTP_SW_RGN"
1472#endif
1473#if OTP_CID_REGION != OTP_CI_RGN
1474#error "incompatible OTP_CI_RGN"
1475#endif
1476
1477/* Redundancy entry definitions */
1478#define	OTP_RCE_ROW_SZ		6
1479#define	OTP_RCE_SIGN_MASK	0x7fff
1480#define	OTP_RCE_ROW_MASK	0x3f
1481#define	OTP_RCE_BITS		21
1482#define	OTP_RCE_SIGN_SZ		15
1483#define	OTP_RCE_BIT0		1
1484
1485#define	OTP_WPR		4
1486#define	OTP_SIGNATURE	0x578a
1487#define	OTP_MAGIC	0x4e56
1488
1489static int
1490hndotp_status(void *oh)
1491{
1492	otpinfo_t *oi = (otpinfo_t *)oh;
1493	return ((int)(oi->hwprot | oi->signvalid));
1494}
1495
1496static int
1497hndotp_size(void *oh)
1498{
1499	otpinfo_t *oi = (otpinfo_t *)oh;
1500	return ((int)(oi->size));
1501}
1502
1503static uint16
1504hndotp_otpr(void *oh, chipcregs_t *cc, uint wn)
1505{
1506	otpinfo_t *oi = (otpinfo_t *)oh;
1507	osl_t *osh;
1508	volatile uint16 *ptr;
1509
1510	ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF));
1511	ASSERT(cc != NULL);
1512
1513	osh = si_osh(oi->sih);
1514
1515	ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP);
1516	return (R_REG(osh, &ptr[wn]));
1517}
1518
1519static uint16
1520hndotp_otproff(void *oh, chipcregs_t *cc, int woff)
1521{
1522	otpinfo_t *oi = (otpinfo_t *)oh;
1523	osl_t *osh;
1524	volatile uint16 *ptr;
1525
1526	ASSERT(woff >= (-((int)oi->size / 2)));
1527	ASSERT(woff < OTP_LIM_OFF);
1528	ASSERT(cc != NULL);
1529
1530	osh = si_osh(oi->sih);
1531
1532	ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP);
1533
1534	return (R_REG(osh, &ptr[(oi->size / 2) + woff]));
1535}
1536
1537static uint16
1538hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx)
1539{
1540	otpinfo_t *oi = (otpinfo_t *)oh;
1541	uint k, row, col;
1542	uint32 otpp, st;
1543	osl_t *osh;
1544
1545	osh = si_osh(oi->sih);
1546	row = idx / 65;
1547	col = idx % 65;
1548
1549	otpp = OTPP_START_BUSY | OTPP_READ |
1550	        ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
1551	        (col & OTPP_COL_MASK);
1552
1553	OTP_DBG(("%s: idx = %d, row = %d, col = %d, otpp = 0x%x", __FUNCTION__,
1554	         idx, row, col, otpp));
1555
1556	W_REG(osh, &cc->otpprog, otpp);
1557	st = R_REG(osh, &cc->otpprog);
1558	for (k = 0; ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
1559		st = R_REG(osh, &cc->otpprog);
1560
1561	if (k >= OTPP_TRIES) {
1562		OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
1563		return 0xffff;
1564	}
1565	if (st & OTPP_READERR) {
1566		OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, idx));
1567		return 0xffff;
1568	}
1569	st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
1570	OTP_DBG((" => %d\n", st));
1571	return (uint16)st;
1572}
1573
1574static void *
1575BCMNMIATTACHFN(hndotp_init)(si_t *sih)
1576{
1577	uint idx;
1578	chipcregs_t *cc;
1579	otpinfo_t *oi;
1580	uint32 cap = 0, clkdiv, otpdiv = 0;
1581	void *ret = NULL;
1582	osl_t *osh;
1583
1584	OTP_MSG(("%s: Use HND OTP controller\n", __FUNCTION__));
1585	oi = &otpinfo;
1586
1587	idx = si_coreidx(sih);
1588	osh = si_osh(oi->sih);
1589
1590	/* Check for otp */
1591	if ((cc = si_setcoreidx(sih, SI_CC_IDX)) != NULL) {
1592		cap = R_REG(osh, &cc->capabilities);
1593		if ((cap & CC_CAP_OTPSIZE) == 0) {
1594			/* Nothing there */
1595			goto out;
1596		}
1597
1598		/* As of right now, support only 4320a2, 4311a1 and 4312 */
1599		ASSERT((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22));
1600		if (!((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22)))
1601			return NULL;
1602
1603		/* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is
1604		 * 8 row (64 bytes) smaller
1605		 */
1606		oi->size = 1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT)
1607			+ CC_CAP_OTPSIZE_BASE);
1608		if (oi->ccrev >= 18) {
1609			oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2);
1610		} else {
1611			OTP_ERR(("Negative otp size, shouldn't happen for programmed chip."));
1612			oi->size = 0;
1613		}
1614
1615		oi->hwprot = (int)(R_REG(osh, &cc->otpstatus) & OTPS_PROTECT);
1616		oi->boundary = -1;
1617
1618		/* Check the region signature */
1619		if (hndotp_otproff(oi, cc, OTP_HWSIGN_OFF) == OTP_SIGNATURE) {
1620			oi->signvalid |= OTP_HW_REGION;
1621			oi->boundary = hndotp_otproff(oi, cc, OTP_BOUNDARY_OFF);
1622		}
1623
1624		if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE)
1625			oi->signvalid |= OTP_SW_REGION;
1626
1627		if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE)
1628			oi->signvalid |= OTP_CID_REGION;
1629
1630		/* Set OTP clkdiv for stability */
1631		if (oi->ccrev == 22)
1632			otpdiv = 12;
1633
1634		if (otpdiv) {
1635			clkdiv = R_REG(osh, &cc->clkdiv);
1636			clkdiv = (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT);
1637			W_REG(osh, &cc->clkdiv, clkdiv);
1638			OTP_MSG(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
1639		}
1640		OSL_DELAY(10);
1641
1642		ret = (void *)oi;
1643	}
1644
1645	OTP_MSG(("%s: ccrev %d\tsize %d bytes\thwprot %x\tsignvalid %x\tboundary %x\n",
1646		__FUNCTION__, oi->ccrev, oi->size, oi->hwprot, oi->signvalid,
1647		oi->boundary));
1648
1649out:	/* All done */
1650	si_setcoreidx(sih, idx);
1651
1652	return ret;
1653}
1654
1655static int
1656hndotp_read_region(void *oh, int region, uint16 *data, uint *wlen)
1657{
1658	otpinfo_t *oi = (otpinfo_t *)oh;
1659	uint32 idx, st;
1660	chipcregs_t *cc;
1661	int i;
1662
1663	/* Only support HW region (no active chips use HND OTP SW region) */
1664	ASSERT(region == OTP_HW_REGION);
1665
1666	OTP_MSG(("%s: region %x wlen %d\n", __FUNCTION__, region, *wlen));
1667
1668	/* Region empty? */
1669	st = oi->hwprot | oi-> signvalid;
1670	if ((st & region) == 0)
1671		return BCME_NOTFOUND;
1672
1673	*wlen = ((int)*wlen < oi->boundary/2) ? *wlen : (uint)oi->boundary/2;
1674
1675	idx = si_coreidx(oi->sih);
1676	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1677	ASSERT(cc != NULL);
1678
1679	for (i = 0; i < (int)*wlen; i++)
1680		data[i] = hndotp_otpr(oh, cc, i);
1681
1682	si_setcoreidx(oi->sih, idx);
1683
1684	return 0;
1685}
1686
1687static int
1688hndotp_read_word(void *oh, uint wn, uint16 *data)
1689{
1690	otpinfo_t *oi = (otpinfo_t *)oh;
1691	uint32 idx;
1692	chipcregs_t *cc;
1693
1694	idx = si_coreidx(oi->sih);
1695	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1696	ASSERT(cc != NULL);
1697
1698	*data = hndotp_otpr(oh, cc, wn);
1699
1700	si_setcoreidx(oi->sih, idx);
1701	return 0;
1702}
1703
1704static int
1705hndotp_nvread(void *oh, char *data, uint *len)
1706{
1707	int rc = 0;
1708	otpinfo_t *oi = (otpinfo_t *)oh;
1709	uint32 base, bound, lim = 0, st;
1710	int i, chunk, gchunks, tsz = 0;
1711	uint32 idx;
1712	chipcregs_t *cc;
1713	uint offset;
1714	uint16 *rawotp = NULL;
1715
1716	/* save the orig core */
1717	idx = si_coreidx(oi->sih);
1718	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1719	ASSERT(cc != NULL);
1720
1721	st = hndotp_status(oh);
1722	if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) {
1723		OTP_ERR(("OTP not programmed\n"));
1724		rc = -1;
1725		goto out;
1726	}
1727
1728	/* Read the whole otp so we can easily manipulate it */
1729	lim = hndotp_size(oh);
1730	if (lim == 0) {
1731		OTP_ERR(("OTP size is 0\n"));
1732		rc = -1;
1733		goto out;
1734	}
1735	if ((rawotp = MALLOC(si_osh(oi->sih), lim)) == NULL) {
1736		OTP_ERR(("Out of memory for rawotp\n"));
1737		rc = -2;
1738		goto out;
1739	}
1740	for (i = 0; i < (int)(lim / 2); i++)
1741		rawotp[i] = hndotp_otpr(oh, cc,  i);
1742
1743	if ((st & OTP_HW_REGION) == 0) {
1744		OTP_ERR(("otp: hw region not written (0x%x)\n", st));
1745
1746		/* This could be a programming failure in the first
1747		 * chunk followed by one or more good chunks
1748		 */
1749		for (i = 0; i < (int)(lim / 2); i++)
1750			if (rawotp[i] == OTP_MAGIC)
1751				break;
1752
1753		if (i < (int)(lim / 2)) {
1754			base = i;
1755			bound = (i * 2) + rawotp[i + 1];
1756			OTP_MSG(("otp: trying chunk at 0x%x-0x%x\n", i * 2, bound));
1757		} else {
1758			OTP_MSG(("otp: unprogrammed\n"));
1759			rc = -3;
1760			goto out;
1761		}
1762	} else {
1763		bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF];
1764
1765		/* There are two cases: 1) The whole otp is used as nvram
1766		 * and 2) There is a hardware header followed by nvram.
1767		 */
1768		if (rawotp[0] == OTP_MAGIC) {
1769			base = 0;
1770			if (bound != rawotp[1])
1771				OTP_MSG(("otp: Bound 0x%x != chunk0 len 0x%x\n", bound,
1772				         rawotp[1]));
1773		} else
1774			base = bound;
1775	}
1776
1777	/* Find and copy the data */
1778
1779	chunk = 0;
1780	gchunks = 0;
1781	i = base / 2;
1782	offset = 0;
1783	while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) {
1784		int dsz, rsz = rawotp[i + 1];
1785
1786		if (((i * 2) + rsz) >= (int)lim) {
1787			OTP_MSG(("  bad chunk size, chunk %d, base 0x%x, size 0x%x\n",
1788			         chunk, i * 2, rsz));
1789			/* Bad length, try to find another chunk anyway */
1790			rsz = 6;
1791		}
1792		if (hndcrc16((uint8 *)&rawotp[i], rsz,
1793		             CRC16_INIT_VALUE) == CRC16_GOOD_VALUE) {
1794			/* Good crc, copy the vars */
1795			OTP_MSG(("  good chunk %d, base 0x%x, size 0x%x\n",
1796			         chunk, i * 2, rsz));
1797			gchunks++;
1798			dsz = rsz - 6;
1799			tsz += dsz;
1800			if (offset + dsz >= *len) {
1801				OTP_MSG(("Out of memory for otp\n"));
1802				goto out;
1803			}
1804			bcopy((char *)&rawotp[i + 2], &data[offset], dsz);
1805			offset += dsz;
1806			/* Remove extra null characters at the end */
1807			while (offset > 1 &&
1808			       data[offset - 1] == 0 && data[offset - 2] == 0)
1809				offset --;
1810			i += rsz / 2;
1811		} else {
1812			/* bad length or crc didn't check, try to find the next set */
1813			OTP_MSG(("  chunk %d @ 0x%x size 0x%x: bad crc, ",
1814			         chunk, i * 2, rsz));
1815			if (rawotp[i + (rsz / 2)] == OTP_MAGIC) {
1816				/* Assume length is good */
1817				i += rsz / 2;
1818			} else {
1819				while (++i < (int)(lim / 2))
1820					if (rawotp[i] == OTP_MAGIC)
1821						break;
1822			}
1823			if (i < (int)(lim / 2))
1824				OTP_MSG(("trying next base 0x%x\n", i * 2));
1825			else
1826				OTP_MSG(("no more chunks\n"));
1827		}
1828		chunk++;
1829	}
1830
1831	OTP_MSG(("  otp size = %d, boundary = 0x%x, nv base = 0x%x\n", lim, bound, base));
1832	if (tsz != 0) {
1833		OTP_MSG(("  Found %d bytes in %d good chunks out of %d\n", tsz, gchunks, chunk));
1834	} else {
1835		OTP_MSG(("  No good chunks found out of %d\n", chunk));
1836	}
1837
1838	*len = offset;
1839
1840out:
1841	if (rawotp)
1842		MFREE(si_osh(oi->sih), rawotp, lim);
1843	si_setcoreidx(oi->sih, idx);
1844
1845	return rc;
1846}
1847
1848#ifdef BCMNVRAMW
1849#if defined(WLTEST)
1850static	uint st_n, st_s, st_hwm, pp_hwm;
1851#ifdef	OTP_FORCEFAIL
1852static	uint forcefail_bitcount = 0;
1853#endif /* OTP_FORCEFAIL */
1854#endif
1855
1856static int
1857hndotp_write_bit(void *oh, chipcregs_t *cc, int bn, bool bit, int no_retry)
1858{
1859	otpinfo_t *oi = (otpinfo_t *)oh;
1860	uint row, col, j, k;
1861	uint32 pwait, init_pwait, otpc, otpp, pst, st;
1862	osl_t *osh;
1863
1864	osh = si_osh(oi->sih);
1865	ASSERT((bit >> 1) == 0);
1866
1867#ifdef	OTP_FORCEFAIL
1868	OTP_MSG(("%s: [0x%x] = 0x%x\n", __FUNCTION__, wn * 2, data));
1869#endif
1870
1871	/* This is bit-at-a-time writing, future cores may do word-at-a-time */
1872	if (oi->ccrev == 12) {
1873		otpc = 0x20000001;
1874		init_pwait = 0x00000200;
1875	} else if (oi->ccrev == 22) {
1876		otpc = 0x20000001;
1877		init_pwait = 0x00000400;
1878	} else {
1879		otpc = 0x20000001;
1880		init_pwait = 0x00004000;
1881	}
1882
1883	pwait = init_pwait;
1884	row = bn / 65;
1885	col = bn % 65;
1886	otpp = OTPP_START_BUSY |
1887		((bit << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) |
1888		((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
1889		(col & OTPP_COL_MASK);
1890	j = 0;
1891	while (1) {
1892		j++;
1893		if (j > 1) {
1894			OTP_DBG(("row %d, col %d, val %d, otpc 0x%x, otpp 0x%x\n",
1895				row, col, bit, (otpc | pwait), otpp));
1896		}
1897		W_REG(osh, &cc->otpcontrol, otpc | pwait);
1898		W_REG(osh, &cc->otpprog, otpp);
1899		pst = R_REG(osh, &cc->otpprog);
1900		for (k = 0; ((pst & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
1901			pst = R_REG(osh, &cc->otpprog);
1902#if defined(WLTEST)
1903		if (k > pp_hwm)
1904			pp_hwm = k;
1905#endif
1906		if (k >= OTPP_TRIES) {
1907			OTP_ERR(("BUSY stuck: pst=0x%x, count=%d\n", pst, k));
1908			st = OTPS_PROGFAIL;
1909			break;
1910		}
1911		st = R_REG(osh, &cc->otpstatus);
1912		if (((st & OTPS_PROGFAIL) == 0) || (pwait == OTPC_PROGWAIT) || (no_retry)) {
1913			break;
1914		} else {
1915			if ((oi->ccrev == 12) || (oi->ccrev == 22))
1916				pwait = (pwait << 3) & OTPC_PROGWAIT;
1917			else
1918				pwait = (pwait << 1) & OTPC_PROGWAIT;
1919			if (pwait == 0)
1920				pwait = OTPC_PROGWAIT;
1921		}
1922	}
1923#if defined(WLTEST)
1924	st_n++;
1925	st_s += j;
1926	if (j > st_hwm)
1927		 st_hwm = j;
1928#ifdef	OTP_FORCEFAIL
1929	if (forcefail_bitcount++ == OTP_FORCEFAIL * 16) {
1930		OTP_DBG(("Forcing PROGFAIL on bit %d (FORCEFAIL = %d/0x%x)\n",
1931			forcefail_bitcount, OTP_FORCEFAIL, OTP_FORCEFAIL));
1932		st = OTPS_PROGFAIL;
1933	}
1934#endif
1935#endif
1936	if (st & OTPS_PROGFAIL) {
1937		OTP_ERR(("After %d tries: otpc = 0x%x, otpp = 0x%x/0x%x, otps = 0x%x\n",
1938		       j, otpc | pwait, otpp, pst, st));
1939		OTP_ERR(("otp prog failed. bit=%d, ppret=%d, ret=%d\n", bit, k, j));
1940		return 1;
1941	}
1942
1943	return 0;
1944}
1945
1946static int
1947hndotp_write_word(void *oh, chipcregs_t *cc, int wn, uint16 data)
1948{
1949	uint base, i;
1950	int err = 0;
1951
1952	OTP_MSG(("%s: wn %d data %x\n", __FUNCTION__, wn, data));
1953
1954	/* There is one test bit for each row */
1955	base = (wn * 16) + (wn / 4);
1956
1957	for (i = 0; i < 16; i++) {
1958		err += hndotp_write_bit(oh, cc, base + i, data & 1, 0);
1959		data >>= 1;
1960		/* abort write after first error to avoid stress the charge-pump */
1961		if (err) {
1962			OTP_DBG(("%s: wn %d fail on bit %d\n", __FUNCTION__, wn, i));
1963			break;
1964		}
1965	}
1966
1967	return err;
1968}
1969
1970static int
1971hndotp_valid_rce(void *oh, chipcregs_t *cc, int i)
1972{
1973	otpinfo_t *oi = (otpinfo_t *)oh;
1974	osl_t *osh;
1975	uint32 hwv, fw, rce, e, sign, row, st;
1976
1977	ASSERT(oi->ccrev >= 18);
1978
1979	/* HW valid bit */
1980	osh = si_osh(oi->sih);
1981	st = R_REG(osh, &cc->otpstatus);
1982	hwv = (st & OTPS_RCEV_MSK) & (1 << (OTPS_RCEV_SHIFT + i));
1983
1984	if (i < 3) {
1985		e = i;
1986		fw = hndotp_size(oh)/2 + OTP_RC0_OFF + e;
1987	} else {
1988		e = i - 3;
1989		fw = hndotp_size(oh)/2 + OTP_RC1_OFF + e;
1990	}
1991
1992	rce = hndotp_otpr(oh, cc, fw+1) << 16 | hndotp_otpr(oh, cc, fw);
1993	rce >>= ((e * OTP_RCE_BITS) + OTP_RCE_BIT0 - (e * 16));
1994	row = rce & OTP_RCE_ROW_MASK;
1995	sign = (rce >> OTP_RCE_ROW_SZ) & OTP_RCE_SIGN_MASK;
1996
1997	OTP_MSG(("rce %d sign %x row %d hwv %x\n", i, sign, row, hwv));
1998
1999	return (sign == OTP_SIGNATURE) ? row : -1;
2000}
2001
2002static int
2003hndotp_write_rce(void *oh, chipcregs_t *cc, int r, uint16* data)
2004{
2005	int i, rce = -1;
2006	uint32	sign;
2007
2008	ASSERT(((otpinfo_t *)oh)->ccrev >= 18);
2009	ASSERT(r >= 0 && r < hndotp_size(oh)/(2*OTP_WPR));
2010	ASSERT(data);
2011
2012	for (rce = OTP_RCE_ROW_SZ -1; rce >= 0; rce--) {
2013		int e, rt, rcr, bit, err = 0;
2014
2015		int rr = hndotp_valid_rce(oh, cc, rce);
2016		/* redundancy row in use already */
2017		if (rr != -1) {
2018			if (rr == r) {
2019				OTP_MSG(("%s: row %d already replaced by RCE %d",
2020					__FUNCTION__, r, rce));
2021				return 0;
2022			}
2023
2024			continue; /* If row used, go for the next row */
2025		}
2026
2027		/*
2028		 * previously used bad rce entry maybe treaed as valid rce and used again, abort on
2029		 * first bit error to avoid stress the charge pump
2030		 */
2031
2032		/* Write the data to the redundant row */
2033		for (i = 0; i < OTP_WPR; i++) {
2034			err += hndotp_write_word(oh, cc, hndotp_size(oh)/2+OTP_RD_OFF+rce*4+i,
2035				data[i]);
2036			if (err) {
2037				OTP_MSG(("fail to write redundant row %d\n", rce));
2038				break;
2039			}
2040		}
2041
2042		/* Now write the redundant row index */
2043		if (rce < 3) {
2044			e = rce;
2045			rcr = hndotp_size(oh)/2 + OTP_RC0_OFF;
2046		} else {
2047			e = rce - 3;
2048			rcr = hndotp_size(oh)/2 + OTP_RC1_OFF;
2049		}
2050
2051		/* Write row numer bit-by-bit */
2052		bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0;
2053		rt = r;
2054		for (i = 0; i < OTP_RCE_ROW_SZ; i++) {
2055			/* If any timeout happened, invalidate the subsequent bits with 0 */
2056			if (hndotp_write_bit(oh, cc, bit, (rt & (err ? 0 : 1)), err)) {
2057				OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row"
2058					" number bit %x\n", __FUNCTION__, r, rce, i));
2059				err++;
2060			}
2061			rt >>= 1;
2062			bit ++;
2063		}
2064
2065		/* Write the RCE signature bit-by-bit */
2066		sign = OTP_SIGNATURE;
2067		for (i = 0; i < OTP_RCE_SIGN_SZ; i++) {
2068			/* If any timeout happened, invalidate the subsequent bits with 0 */
2069			if (hndotp_write_bit(oh, cc, bit, (sign & (err ? 0 : 1)), err)) {
2070				OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row"
2071					" number bit %x\n", __FUNCTION__, r, rce, i));
2072				err++;
2073			}
2074			sign >>= 1;
2075			bit ++;
2076		}
2077
2078		if (err) {
2079			OTP_ERR(("%s: row %d not fixed by RCE %d due to %d timeouts. try next"
2080				" RCE\n", __FUNCTION__, r, rce, err));
2081			continue;
2082		} else {
2083			OTP_MSG(("%s: Fixed row %d by RCE %d\n", __FUNCTION__, r, rce));
2084			return BCME_OK;
2085		}
2086	}
2087
2088	OTP_ERR(("All RCE's are in use. Failed fixing OTP.\n"));
2089	/* Fatal error, unfixable. MFGC will have to fail. Board needs to be discarded!!  */
2090	return BCME_NORESOURCE;
2091}
2092
2093/* Write a row and fix it with RCE if any error detected */
2094static int
2095hndotp_write_row(void *oh, chipcregs_t *cc, int wn, uint16* data, bool rewrite)
2096{
2097	otpinfo_t *oi = (otpinfo_t *)oh;
2098	int err = 0, i;
2099
2100	ASSERT(wn % OTP_WPR == 0);
2101
2102	/* Write the data */
2103	for (i = 0; i < OTP_WPR; i++) {
2104		if (rewrite && (data[i] == hndotp_otpr(oh, cc, wn+i)))
2105			continue;
2106
2107		err += hndotp_write_word(oh, cc, wn + i, data[i]);
2108	}
2109
2110	/* Fix this row if any error */
2111	if (err && (oi->ccrev >= 18)) {
2112		OTP_DBG(("%s: %d write errors in row %d. Fixing...\n", __FUNCTION__, err, wn/4));
2113		if ((err = hndotp_write_rce(oh, cc, wn / OTP_WPR, data)))
2114			OTP_MSG(("%s: failed to fix row %d\n", __FUNCTION__, wn/4));
2115	}
2116
2117	return err;
2118}
2119
2120/* expects the caller to disable interrupts before calling this routine */
2121static int
2122hndotp_write_region(void *oh, int region, uint16 *data, uint wlen)
2123{
2124	otpinfo_t *oi = (otpinfo_t *)oh;
2125	uint32 st;
2126	uint wn, base = 0, lim;
2127	int ret = BCME_OK;
2128	uint idx;
2129	chipcregs_t *cc;
2130	bool rewrite = FALSE;
2131	uint32	save_clk;
2132
2133	ASSERT(wlen % OTP_WPR == 0);
2134
2135	idx = si_coreidx(oi->sih);
2136	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2137	ASSERT(cc != NULL);
2138
2139	/* Check valid region */
2140	if ((region != OTP_HW_REGION) &&
2141	    (region != OTP_SW_REGION) &&
2142	    (region != OTP_CID_REGION)) {
2143		ret = BCME_BADARG;
2144		goto out;
2145	}
2146
2147	/* Region already written? */
2148	st = oi->hwprot | oi-> signvalid;
2149	if ((st & region) != 0)
2150		rewrite = TRUE;
2151
2152	/* HW and CID have to be written before SW */
2153	if ((((st & (OTP_HW_REGION | OTP_CID_REGION)) == 0) &&
2154		(st & OTP_SW_REGION) != 0)) {
2155		OTP_ERR(("%s: HW/CID region should be programmed first\n", __FUNCTION__));
2156		ret = BCME_BADARG;
2157		goto out;
2158	}
2159
2160	/* Bounds for the region */
2161	lim = (oi->size / 2) + OTP_SWLIM_OFF;
2162	if (region == OTP_HW_REGION) {
2163		base = 0;
2164	} else if (region == OTP_SW_REGION) {
2165		base = oi->boundary / 2;
2166	} else if (region == OTP_CID_REGION) {
2167		base = (oi->size / 2) + OTP_CID_OFF;
2168		lim = (oi->size / 2) + OTP_LIM_OFF;
2169	}
2170
2171	if (wlen > (lim - base)) {
2172		ret = BCME_BUFTOOLONG;
2173		goto out;
2174	}
2175	lim = base + wlen;
2176
2177#if defined(WLTEST)
2178	st_n = st_s = st_hwm = pp_hwm = 0;
2179#endif
2180
2181	/* force ALP for progrramming stability */
2182	save_clk = R_REG(oi->osh, &cc->clk_ctl_st);
2183	OR_REG(oi->osh, &cc->clk_ctl_st, CCS_FORCEALP);
2184	OSL_DELAY(10);
2185
2186	/* Write the data row by row */
2187	for (wn = base; wn < lim; wn += OTP_WPR, data += OTP_WPR) {
2188		if ((ret = hndotp_write_row(oh, cc, wn, data, rewrite)) != 0) {
2189			if (ret == BCME_NORESOURCE) {
2190				OTP_ERR(("%s: Abort at word %x\n", __FUNCTION__, wn));
2191				break;
2192			}
2193		}
2194	}
2195
2196	/* Don't need to update signature & boundary if rewrite */
2197	if (rewrite)
2198		goto out_rclk;
2199
2200	/* Done with the data, write the signature & boundary if needed */
2201	if (region == OTP_HW_REGION) {
2202		if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF, lim * 2) != 0) {
2203			ret = BCME_NORESOURCE;
2204			goto out_rclk;
2205		}
2206		if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF,
2207			OTP_SIGNATURE) != 0) {
2208			ret = BCME_NORESOURCE;
2209			goto out_rclk;
2210		}
2211		oi->boundary = lim * 2;
2212		oi->signvalid |= OTP_HW_REGION;
2213	} else if (region == OTP_SW_REGION) {
2214		if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_SWSIGN_OFF,
2215			OTP_SIGNATURE) != 0) {
2216			ret = BCME_NORESOURCE;
2217			goto out_rclk;
2218		}
2219		oi->signvalid |= OTP_SW_REGION;
2220	} else if (region == OTP_CID_REGION) {
2221		if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_CIDSIGN_OFF,
2222			OTP_SIGNATURE) != 0) {
2223			ret = BCME_NORESOURCE;
2224			goto out_rclk;
2225		}
2226		oi->signvalid |= OTP_CID_REGION;
2227	}
2228
2229out_rclk:
2230	/* Restore clock */
2231	W_REG(oi->osh, &cc->clk_ctl_st, save_clk);
2232
2233out:
2234#if defined(WLTEST)
2235	OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n",
2236		st_n, st_s, st_n, st_n?(st_s / st_n):0, st_hwm, pp_hwm));
2237#endif
2238
2239	si_setcoreidx(oi->sih, idx);
2240
2241	return ret;
2242}
2243
2244/* For HND OTP, there's no space for appending after filling in SROM image */
2245static int
2246hndotp_cis_append_region(si_t *sih, int region, char *vars, int count)
2247{
2248	return otp_write_region(sih, region, (uint16*)vars, count/2);
2249}
2250
2251/*
2252 * Fill all unwritten RCE signature with 0 and return the number of them.
2253 * HNDOTP needs lock due to the randomness of unprogrammed content.
2254 */
2255static int
2256hndotp_lock(void *oh)
2257{
2258	otpinfo_t *oi = (otpinfo_t *)oh;
2259	int i, j, e, rcr, bit, ret = 0;
2260	uint32 st, idx;
2261	chipcregs_t *cc;
2262
2263	ASSERT(oi->ccrev >= 18);
2264
2265	idx = si_coreidx(oi->sih);
2266	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2267	ASSERT(cc != NULL);
2268
2269	/* Region already written? */
2270	st = oi->hwprot | oi-> signvalid;
2271	if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == 0) {
2272		si_setcoreidx(oi->sih, idx);
2273		return BCME_NOTREADY;	/* Don't lock unprogrammed OTP */
2274	}
2275
2276	/* Find the highest valid RCE */
2277	for (i = 0; i < OTP_RCE_ROW_SZ -1; i++) {
2278		if ((hndotp_valid_rce(oh, cc, i) != -1))
2279			break;
2280	}
2281	i--;	/* Start invalidating from the next RCE */
2282
2283	for (; i >= 0; i--) {
2284		if ((hndotp_valid_rce(oh, cc, i) == -1)) {
2285
2286			ret++;	/* This is a unprogrammed row */
2287
2288			/* Invalidate the row with 0 */
2289			if (i < 3) {
2290				e = i;
2291				rcr = hndotp_size(oh)/2 + OTP_RC0_OFF;
2292			} else {
2293				e = i - 3;
2294				rcr = hndotp_size(oh)/2 + OTP_RC1_OFF;
2295			}
2296
2297			/* Fill row numer and signature with 0 bit-by-bit */
2298			bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0;
2299			for (j = 0; j < (OTP_RCE_ROW_SZ + OTP_RCE_SIGN_SZ); j++) {
2300				hndotp_write_bit(oh, cc, bit, 0, 1);
2301				bit ++;
2302			}
2303
2304			OTP_MSG(("locking rce %d\n", i));
2305		}
2306	}
2307
2308	si_setcoreidx(oi->sih, idx);
2309
2310	return ret;
2311}
2312
2313/* expects the caller to disable interrupts before calling this routine */
2314static int
2315hndotp_nvwrite(void *oh, uint16 *data, uint wlen)
2316{
2317	otpinfo_t *oi = (otpinfo_t *)oh;
2318	uint32 st;
2319	uint16 crc, clen, *p, hdr[2];
2320	uint wn, base = 0, lim;
2321	int err, gerr = 0;
2322	uint idx;
2323	chipcregs_t *cc;
2324
2325	/* otp already written? */
2326	st = oi->hwprot | oi-> signvalid;
2327	if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == (OTP_HW_REGION | OTP_SW_REGION))
2328		return BCME_EPERM;
2329
2330	/* save the orig core */
2331	idx = si_coreidx(oi->sih);
2332	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2333	ASSERT(cc != NULL);
2334
2335	/* Bounds for the region */
2336	lim = (oi->size / 2) + OTP_SWLIM_OFF;
2337	base = 0;
2338
2339	/* Look for possible chunks from the end down */
2340	wn = lim;
2341	while (wn > 0) {
2342		wn--;
2343		if (hndotp_otpr(oh, cc, wn) == OTP_MAGIC) {
2344			base = wn + (hndotp_otpr(oh, cc, wn + 1) / 2);
2345			break;
2346		}
2347	}
2348	if (base == 0) {
2349		OTP_MSG(("Unprogrammed otp\n"));
2350	} else {
2351		OTP_MSG(("Found some chunks, skipping to 0x%x\n", base * 2));
2352	}
2353	if ((wlen + 3) > (lim - base)) {
2354		err =  BCME_NORESOURCE;
2355		goto out;
2356	}
2357
2358#if defined(WLTEST)
2359	st_n = st_s = st_hwm = pp_hwm = 0;
2360#endif
2361
2362	/* Prepare the header and crc */
2363	hdr[0] = OTP_MAGIC;
2364	hdr[1] = (wlen + 3) * 2;
2365	crc = hndcrc16((uint8 *)hdr, sizeof(hdr), CRC16_INIT_VALUE);
2366	crc = hndcrc16((uint8 *)data, wlen * 2, crc);
2367	crc = ~crc;
2368
2369	do {
2370		p = data;
2371		wn = base + 2;
2372		lim = base + wlen + 2;
2373
2374		OTP_MSG(("writing chunk, 0x%x bytes @ 0x%x-0x%x\n", wlen * 2,
2375		         base * 2, (lim + 1) * 2));
2376
2377		/* Write the header */
2378		err = hndotp_write_word(oh, cc, base, hdr[0]);
2379
2380		/* Write the data */
2381		while (wn < lim) {
2382			err += hndotp_write_word(oh, cc, wn++, *p++);
2383
2384			/* If there has been an error, close this chunk */
2385			if (err != 0) {
2386				OTP_MSG(("closing early @ 0x%x\n", wn * 2));
2387				break;
2388			}
2389		}
2390
2391		/* If we wrote the whole chunk, write the crc */
2392		if (wn == lim) {
2393			OTP_MSG(("  whole chunk written, crc = 0x%x\n", crc));
2394			err += hndotp_write_word(oh, cc, wn++, crc);
2395			clen = hdr[1];
2396		} else {
2397			/* If there was an error adjust the count to point to
2398			 * the word after the error so we can start the next
2399			 * chunk there.
2400			 */
2401			clen = (wn - base) * 2;
2402			OTP_MSG(("  partial chunk written, chunk len = 0x%x\n", clen));
2403		}
2404		/* And now write the chunk length */
2405		err += hndotp_write_word(oh, cc, base + 1, clen);
2406
2407		if (base == 0) {
2408			/* Write the signature and boundary if this is the HW region,
2409			 * but don't report failure if either of these 2 writes fail.
2410			 */
2411			if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF,
2412			    wn * 2) == 0)
2413				gerr += hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF,
2414				                       OTP_SIGNATURE);
2415			else
2416				gerr++;
2417			oi->boundary = wn * 2;
2418			oi->signvalid |= OTP_HW_REGION;
2419		}
2420
2421		if (err != 0) {
2422			gerr += err;
2423			/* Errors, do it all over again if there is space left */
2424			if ((wlen + 3) <= ((oi->size / 2) + OTP_SWLIM_OFF - wn)) {
2425				base = wn;
2426				lim = base + wlen + 2;
2427				OTP_ERR(("Programming errors, retry @ 0x%x\n", wn * 2));
2428			} else {
2429				OTP_ERR(("Programming errors, no space left ( 0x%x)\n", wn * 2));
2430				break;
2431			}
2432		}
2433	} while (err != 0);
2434
2435	OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n",
2436	       st_n, st_s, st_n, st_s / st_n, st_hwm, pp_hwm));
2437
2438	if (gerr != 0)
2439		OTP_MSG(("programming %s after %d errors\n", (err == 0) ? "succedded" : "failed",
2440		         gerr));
2441out:
2442	/* done */
2443	si_setcoreidx(oi->sih, idx);
2444
2445	if (err)
2446		return BCME_ERROR;
2447	else
2448		return 0;
2449}
2450#endif /* BCMNVRAMW */
2451
2452#if defined(WLTEST)
2453static uint16
2454hndotp_otprb16(void *oh, chipcregs_t *cc, uint wn)
2455{
2456	uint base, i;
2457	uint16 val, bit;
2458
2459	base = (wn * 16) + (wn / 4);
2460	val = 0;
2461	for (i = 0; i < 16; i++) {
2462		if ((bit = hndotp_read_bit(oh, cc, base + i)) == 0xffff)
2463			break;
2464		val = val | (bit << i);
2465	}
2466	if (i < 16)
2467		val = 0xaaaa;
2468	return val;
2469}
2470
2471static int
2472hndotp_dump(void *oh, int arg, char *buf, uint size)
2473{
2474	otpinfo_t *oi = (otpinfo_t *)oh;
2475	chipcregs_t *cc;
2476	uint idx, i, count, lil;
2477	uint16 val;
2478	struct bcmstrbuf b;
2479
2480	idx = si_coreidx(oi->sih);
2481	cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2482	ASSERT(cc != NULL);
2483
2484	if (arg >= 16)
2485		arg -= 16;
2486
2487	if (arg == 2) {
2488		count = 66 * 4;
2489		lil = 3;
2490	} else {
2491		count = (oi->size / 2) + OTP_RC_LIM_OFF;
2492		lil = 7;
2493	}
2494
2495	OTP_MSG(("%s: arg %d, size %d, words %d\n", __FUNCTION__, arg, size, count));
2496	bcm_binit(&b, buf, size);
2497	for (i = 0; i < count; i++) {
2498		if ((i & lil) == 0)
2499			bcm_bprintf(&b, "0x%04x:", 2 * i);
2500
2501		if (arg == 0)
2502			val = hndotp_otpr(oh, cc, i);
2503		else
2504			val = hndotp_otprb16(oi, cc, i);
2505		bcm_bprintf(&b, " 0x%04x", val);
2506		if ((i & lil) == lil) {
2507			if (arg == 2) {
2508				bcm_bprintf(&b, " %d\n",
2509				            hndotp_read_bit(oh, cc, ((i / 4) * 65) + 64) & 1);
2510			} else {
2511				bcm_bprintf(&b, "\n");
2512			}
2513		}
2514	}
2515	if ((i & lil) != lil)
2516		bcm_bprintf(&b, "\n");
2517
2518	OTP_MSG(("%s: returning %d, left %d, wn %d\n",
2519		__FUNCTION__, (int)(b.buf - b.origbuf), b.size, i));
2520
2521	si_setcoreidx(oi->sih, idx);
2522
2523	return ((int)(b.buf - b.origbuf));
2524}
2525#endif
2526
2527static otp_fn_t hndotp_fn = {
2528	(otp_size_t)hndotp_size,
2529	(otp_read_bit_t)hndotp_read_bit,
2530
2531	(otp_init_t)hndotp_init,
2532	(otp_read_region_t)hndotp_read_region,
2533	(otp_nvread_t)hndotp_nvread,
2534#ifdef BCMNVRAMW
2535	(otp_write_region_t)hndotp_write_region,
2536	(otp_cis_append_region_t)hndotp_cis_append_region,
2537	(otp_lock_t)hndotp_lock,
2538	(otp_nvwrite_t)hndotp_nvwrite,
2539#endif /* BCMNVRAMW */
2540
2541#if defined(WLTEST)
2542	(otp_dump_t)hndotp_dump,
2543#endif
2544
2545	(otp_status_t)hndotp_status,
2546#ifdef BCMNVRAMW
2547	(otp_write_word_t)NULL,
2548#endif /* BCMNVRAMW */
2549	(otp_read_word_t)hndotp_read_word,
2550};
2551
2552#endif /* BCMHNDOTP */
2553
2554/*
2555 * Common Code: Compiled for IPX / HND / AUTO
2556 *	otp_status()
2557 *	otp_size()
2558 *	otp_read_bit()
2559 *	otp_init()
2560 * 	otp_read_region()
2561 * 	otp_read_word()
2562 * 	otp_nvread()
2563 * 	otp_write_region()
2564 * 	otp_write_word()
2565 * 	otp_cis_append_region()
2566 * 	otp_lock()
2567 * 	otp_nvwrite()
2568 * 	otp_dump()
2569 */
2570
2571int
2572otp_status(void *oh)
2573{
2574	otpinfo_t *oi = (otpinfo_t *)oh;
2575
2576	return oi->fn->status(oh);
2577}
2578
2579int
2580otp_size(void *oh)
2581{
2582	otpinfo_t *oi = (otpinfo_t *)oh;
2583
2584	return oi->fn->size(oh);
2585}
2586
2587uint16
2588otp_read_bit(void *oh, uint offset)
2589{
2590	otpinfo_t *oi = (otpinfo_t *)oh;
2591	uint idx = si_coreidx(oi->sih);
2592	chipcregs_t *cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2593	uint16 readBit = (uint16)oi->fn->read_bit(oh, cc, offset);
2594	si_setcoreidx(oi->sih, idx);
2595	return readBit;
2596}
2597
2598void *
2599BCMNMIATTACHFN(otp_init)(si_t *sih)
2600{
2601	otpinfo_t *oi;
2602	void *ret = NULL;
2603
2604	oi = &otpinfo;
2605	bzero(oi, sizeof(otpinfo_t));
2606
2607	oi->ccrev = sih->ccrev;
2608
2609#ifdef BCMIPXOTP
2610	if (OTPTYPE_IPX(oi->ccrev))
2611		oi->fn = &ipxotp_fn;
2612#endif
2613
2614#ifdef BCMHNDOTP
2615	if (OTPTYPE_HND(oi->ccrev))
2616		oi->fn = &hndotp_fn;
2617#endif
2618
2619	if (oi->fn == NULL) {
2620		OTP_ERR(("otp_init: unsupported OTP type\n"));
2621		return NULL;
2622	}
2623
2624	oi->sih = sih;
2625	oi->osh = si_osh(oi->sih);
2626
2627	ret = (oi->fn->init)(sih);
2628
2629	return ret;
2630}
2631
2632int
2633BCMNMIATTACHFN(otp_read_region)(si_t *sih, int region, uint16 *data, uint *wlen)
2634{
2635	bool wasup = FALSE;
2636	void *oh;
2637	int err = 0;
2638
2639	if (!(wasup = si_is_otp_powered(sih)))
2640		si_otp_power(sih, TRUE);
2641
2642	if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2643		err = BCME_NOTREADY;
2644		goto out;
2645	}
2646
2647	oh = otp_init(sih);
2648	if (oh == NULL) {
2649		OTP_ERR(("otp_init failed.\n"));
2650		err = BCME_ERROR;
2651		goto out;
2652	}
2653
2654	err = (((otpinfo_t*)oh)->fn->read_region)(oh, region, data, wlen);
2655
2656out:
2657	if (!wasup)
2658		si_otp_power(sih, FALSE);
2659
2660	return err;
2661}
2662
2663int
2664otp_read_word(si_t *sih, uint wn, uint16 *data)
2665{
2666	bool wasup = FALSE;
2667	void *oh;
2668	int err = 0;
2669
2670	if (!(wasup = si_is_otp_powered(sih)))
2671		si_otp_power(sih, TRUE);
2672
2673	if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2674		err = BCME_NOTREADY;
2675		goto out;
2676	}
2677
2678	oh = otp_init(sih);
2679	if (oh == NULL) {
2680		OTP_ERR(("otp_init failed.\n"));
2681		err = BCME_ERROR;
2682		goto out;
2683	}
2684
2685	if (((otpinfo_t*)oh)->fn->read_word == NULL) {
2686		err = BCME_UNSUPPORTED;
2687		goto out;
2688	}
2689	err = (((otpinfo_t*)oh)->fn->read_word)(oh, wn, data);
2690
2691out:
2692	if (!wasup)
2693		si_otp_power(sih, FALSE);
2694
2695	return err;
2696}
2697
2698int
2699otp_nvread(void *oh, char *data, uint *len)
2700{
2701	otpinfo_t *oi = (otpinfo_t *)oh;
2702
2703	return oi->fn->nvread(oh, data, len);
2704}
2705
2706#ifdef BCMNVRAMW
2707int
2708BCMNMIATTACHFN(otp_write_region)(si_t *sih, int region, uint16 *data, uint wlen)
2709{
2710	bool wasup = FALSE;
2711	void *oh;
2712	int err = 0;
2713
2714	if (!(wasup = si_is_otp_powered(sih)))
2715		si_otp_power(sih, TRUE);
2716
2717	if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2718		err = BCME_NOTREADY;
2719		goto out;
2720	}
2721
2722	oh = otp_init(sih);
2723	if (oh == NULL) {
2724		OTP_ERR(("otp_init failed.\n"));
2725		err = BCME_ERROR;
2726		goto out;
2727	}
2728
2729	err = (((otpinfo_t*)oh)->fn->write_region)(oh, region, data, wlen);
2730
2731out:
2732	if (!wasup)
2733		si_otp_power(sih, FALSE);
2734
2735	return err;
2736}
2737
2738int
2739otp_write_word(si_t *sih, uint wn, uint16 data)
2740{
2741	bool wasup = FALSE;
2742	void *oh;
2743	int err = 0;
2744
2745	if (!(wasup = si_is_otp_powered(sih)))
2746		si_otp_power(sih, TRUE);
2747
2748	if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2749		err = BCME_NOTREADY;
2750		goto out;
2751	}
2752
2753	oh = otp_init(sih);
2754	if (oh == NULL) {
2755		OTP_ERR(("otp_init failed.\n"));
2756		err = BCME_ERROR;
2757		goto out;
2758	}
2759
2760	if (((otpinfo_t*)oh)->fn->write_word == NULL) {
2761		err = BCME_UNSUPPORTED;
2762		goto out;
2763	}
2764	err = (((otpinfo_t*)oh)->fn->write_word)(oh, wn, data);
2765
2766out:
2767	if (!wasup)
2768		si_otp_power(sih, FALSE);
2769
2770	return err;
2771}
2772
2773int
2774otp_cis_append_region(si_t *sih, int region, char *vars, int count)
2775{
2776	void *oh = otp_init(sih);
2777
2778	if (oh == NULL) {
2779		OTP_ERR(("otp_init failed.\n"));
2780		return -1;
2781	}
2782	return (((otpinfo_t*)oh)->fn->cis_append_region)(sih, region, vars, count);
2783}
2784
2785int
2786otp_lock(si_t *sih)
2787{
2788	bool wasup = FALSE;
2789	void *oh;
2790	int ret = 0;
2791
2792	if (!(wasup = si_is_otp_powered(sih)))
2793		si_otp_power(sih, TRUE);
2794
2795	if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2796		ret = BCME_NOTREADY;
2797		goto out;
2798	}
2799
2800	oh = otp_init(sih);
2801	if (oh == NULL) {
2802		OTP_ERR(("otp_init failed.\n"));
2803		ret = BCME_ERROR;
2804		goto out;
2805	}
2806
2807	ret = (((otpinfo_t*)oh)->fn->lock)(oh);
2808
2809out:
2810	if (!wasup)
2811		si_otp_power(sih, FALSE);
2812
2813	return ret;
2814}
2815
2816int
2817otp_nvwrite(void *oh, uint16 *data, uint wlen)
2818{
2819	otpinfo_t *oi = (otpinfo_t *)oh;
2820
2821	return oi->fn->nvwrite(oh, data, wlen);
2822}
2823#endif /* BCMNVRAMW */
2824
2825#if defined(WLTEST)
2826int
2827otp_dump(void *oh, int arg, char *buf, uint size)
2828{
2829	otpinfo_t *oi = (otpinfo_t *)oh;
2830
2831	return oi->fn->dump(oh, arg, buf, size);
2832}
2833
2834int
2835otp_dumpstats(void *oh, int arg, char *buf, uint size)
2836{
2837	otpinfo_t *oi = (otpinfo_t *)oh;
2838	struct bcmstrbuf b;
2839
2840	bcm_binit(&b, buf, size);
2841
2842	bcm_bprintf(&b, "\nOTP, ccrev 0x%04x\n", oi->ccrev);
2843#if defined(BCMIPXOTP)
2844	bcm_bprintf(&b, "wsize %d rows %d cols %d\n", oi->wsize, oi->rows, oi->cols);
2845	bcm_bprintf(&b, "hwbase %d hwlim %d swbase %d swlim %d fusebits %d\n",
2846		oi->hwbase, oi->hwlim, oi->swbase, oi->swlim, oi->fbase, oi->flim, oi->fusebits);
2847	bcm_bprintf(&b, "otpgu_base %d status %d\n", oi->otpgu_base, oi->status);
2848#endif
2849#if defined(BCMHNDOTP)
2850	bcm_bprintf(&b, "OLD OTP, size %d hwprot 0x%x signvalid 0x%x boundary %d\n",
2851		oi->size, oi->hwprot, oi->signvalid, oi->boundary);
2852#endif
2853	bcm_bprintf(&b, "\n");
2854
2855	return 200;	/* real buf length, pick one to cover above print */
2856}
2857
2858#endif
2859