K2.6 patches and update.
[tomato.git] / release / src-rt / shared / bcmotp.c
blobd57b2fd443e9b2a09254ad0db70cf953e1a84bd8
1 /*
2 * OTP support.
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.
18 * $Id: bcmotp.c,v 1.137.2.23 2011-02-01 06:16:34 Exp $
21 #include <typedefs.h>
22 #include <bcmdefs.h>
23 #include <osl.h>
24 #include <bcmdevs.h>
25 #include <bcmutils.h>
26 #include <bcmnvram.h>
27 #include <siutils.h>
28 #include <bcmendian.h>
29 #include <hndsoc.h>
30 #include <sbchipc.h>
31 #include <bcmotp.h>
34 * There are two different OTP controllers so far:
35 * 1. new IPX OTP controller: chipc 21, >=23
36 * 2. older HND OTP controller: chipc 12, 17, 22
38 * Define BCMHNDOTP to include support for the HND OTP controller.
39 * Define BCMIPXOTP to include support for the IPX OTP controller.
41 * NOTE 1: More than one may be defined
42 * NOTE 2: If none are defined, the default is to include them all.
45 #if !defined(BCMHNDOTP) && !defined(BCMIPXOTP)
46 #define BCMHNDOTP 1
47 #define BCMIPXOTP 1
48 #endif
50 #define OTPTYPE_HND(ccrev) ((ccrev) < 21 || (ccrev) == 22)
51 #define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23)
53 #define OTP_ERR_VAL 0x0001
54 #define OTP_MSG_VAL 0x0002
55 #define OTP_DBG_VAL 0x0004
56 uint32 otp_msg_level = OTP_ERR_VAL;
58 #if defined(BCMDBG) || defined(BCMDBG_ERR)
59 #define OTP_ERR(args) do {if (otp_msg_level & OTP_ERR_VAL) printf args;} while (0)
60 #else
61 #define OTP_ERR(args)
62 #endif
64 #ifdef BCMDBG
65 #define OTP_MSG(args) do {if (otp_msg_level & OTP_MSG_VAL) printf args;} while (0)
66 #define OTP_DBG(args) do {if (otp_msg_level & OTP_DBG_VAL) printf args;} while (0)
67 #else
68 #define OTP_MSG(args)
69 #define OTP_DBG(args)
70 #endif
72 #define OTPP_TRIES 10000000 /* # of tries for OTPP */
74 #ifdef BCMIPXOTP
75 #define MAXNUMRDES 9 /* Maximum OTP redundancy entries */
76 #endif
78 /* OTP common function type */
79 typedef int (*otp_status_t)(void *oh);
80 typedef int (*otp_size_t)(void *oh);
81 typedef void* (*otp_init_t)(si_t *sih);
82 typedef uint16 (*otp_read_bit_t)(void *oh, chipcregs_t *cc, uint off);
83 typedef int (*otp_read_region_t)(si_t *sih, int region, uint16 *data, uint *wlen);
84 typedef int (*otp_nvread_t)(void *oh, char *data, uint *len);
85 typedef int (*otp_write_region_t)(void *oh, int region, uint16 *data, uint wlen);
86 typedef int (*otp_cis_append_region_t)(si_t *sih, int region, char *vars, int count);
87 typedef int (*otp_lock_t)(si_t *sih);
88 typedef int (*otp_nvwrite_t)(void *oh, uint16 *data, uint wlen);
89 typedef int (*otp_dump_t)(void *oh, int arg, char *buf, uint size);
90 typedef int (*otp_write_word_t)(void *oh, uint wn, uint16 data);
91 typedef int (*otp_read_word_t)(void *oh, uint wn, uint16 *data);
93 /* OTP function struct */
94 typedef struct otp_fn_s {
95 otp_size_t size;
96 otp_read_bit_t read_bit;
98 otp_init_t init;
99 otp_read_region_t read_region;
100 otp_nvread_t nvread;
101 #ifdef BCMNVRAMW
102 otp_write_region_t write_region;
103 otp_cis_append_region_t cis_append_region;
104 otp_lock_t lock;
105 otp_nvwrite_t nvwrite;
106 #endif /* BCMNVRAMW */
108 #if defined(WLTEST)
109 otp_dump_t dump;
110 #endif
112 otp_status_t status;
113 #ifdef BCMNVRAMW
114 otp_write_word_t write_word;
115 #endif /* BCMNVRAMW */
116 otp_read_word_t read_word;
117 } otp_fn_t;
119 typedef struct {
120 uint ccrev; /* chipc revision */
121 otp_fn_t *fn; /* OTP functions */
122 si_t *sih; /* Saved sb handle */
123 osl_t *osh;
125 #ifdef BCMIPXOTP
126 /* IPX OTP section */
127 uint16 wsize; /* Size of otp in words */
128 uint16 rows; /* Geometry */
129 uint16 cols; /* Geometry */
130 uint32 status; /* Flag bits (lock/prog/rv).
131 * (Reflected only when OTP is power cycled)
133 uint16 hwbase; /* hardware subregion offset */
134 uint16 hwlim; /* hardware subregion boundary */
135 uint16 swbase; /* software subregion offset */
136 uint16 swlim; /* software subregion boundary */
137 uint16 fbase; /* fuse subregion offset */
138 uint16 flim; /* fuse subregion boundary */
139 int otpgu_base; /* offset to General Use Region */
140 uint16 fusebits; /* num of fusebits */
141 #ifdef BCMNVRAMW
142 struct {
143 uint8 width; /* entry width in bits */
144 uint8 val_shift; /* value bit offset in the entry */
145 uint8 offsets; /* # entries */
146 uint8 stat_shift; /* valid bit in otpstatus */
147 uint16 offset[MAXNUMRDES]; /* entry offset in OTP */
148 } rde_cb; /* OTP redundancy control blocks */
149 #endif /* BCMNVRAMW */
150 #endif /* BCMIPXOTP */
152 #ifdef BCMHNDOTP
153 /* HND OTP section */
154 uint size; /* Size of otp in bytes */
155 uint hwprot; /* Hardware protection bits */
156 uint signvalid; /* Signature valid bits */
157 int boundary; /* hw/sw boundary */
158 #endif /* BCMHNDOTP */
159 } otpinfo_t;
161 static otpinfo_t otpinfo;
164 * IPX OTP Code
166 * Exported functions:
167 * ipxotp_status()
168 * ipxotp_size()
169 * ipxotp_init()
170 * ipxotp_read_bit()
171 * ipxotp_read_region()
172 * ipxotp_read_word()
173 * ipxotp_nvread()
174 * ipxotp_write_region()
175 * ipxotp_write_word()
176 * ipxotp_cis_append_region()
177 * ipxotp_lock()
178 * ipxotp_nvwrite()
179 * ipxotp_dump()
181 * IPX internal functions:
182 * ipxotp_otpr()
183 * _ipxotp_init()
184 * ipxotp_write_bit()
185 * ipxotp_otpwb16()
186 * ipxotp_write_rde()
187 * ipxotp_fix_word16()
188 * ipxotp_check_word16()
189 * ipxotp_max_rgnsz()
190 * ipxotp_otprb16()
194 #ifdef BCMIPXOTP
196 #define HWSW_RGN(rgn) (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
198 /* OTP layout */
199 /* CC revs 21, 24 and 27 OTP General Use Region word offset */
200 #define REVA4_OTPGU_BASE 12
202 /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
203 #define REVB8_OTPGU_BASE 20
205 /* CC rev 36 OTP General Use Region word offset */
206 #define REV36_OTPGU_BASE 12
208 /* Subregion word offsets in General Use region */
209 #define OTPGU_HSB_OFF 0
210 #define OTPGU_SFB_OFF 1
211 #define OTPGU_CI_OFF 2
212 #define OTPGU_P_OFF 3
213 #define OTPGU_SROM_OFF 4
215 /* Flag bit offsets in General Use region */
216 #define OTPGU_HWP_OFF 60
217 #define OTPGU_SWP_OFF 61
218 #define OTPGU_CIP_OFF 62
219 #define OTPGU_FUSEP_OFF 63
220 #define OTPGU_CIP_MSK 0x4000
221 #define OTPGU_P_MSK 0xf000
222 #define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16)
224 /* LOCK but offset */
225 #define OTP_LOCK_ROW1_LOC_OFF 63 /* 1st ROW lock bit */
226 #define OTP_LOCK_ROW2_LOC_OFF 127 /* 2nd ROW lock bit */
227 #define OTP_LOCK_RD_LOC_OFF 128 /* Redundnancy Region lock bit */
228 #define OTP_LOCK_GU_LOC_OFF 129 /* General User Region lock bit */
231 /* OTP Size */
232 #define OTP_SZ_FU_324 ((ROUNDUP(324,8))/8) /* 324 bits */
233 #define OTP_SZ_FU_288 (288/8) /* 288 bits */
234 #define OTP_SZ_FU_216 (216/8) /* 216 bits */
235 #define OTP_SZ_FU_72 (72/8) /* 72 bits */
236 #define OTP_SZ_CHECKSUM (16/8) /* 16 bits */
237 #define OTP4315_SWREG_SZ 178 /* 178 bytes */
238 #define OTP_SZ_FU_144 (144/8) /* 144 bits */
239 #define OTP_SZ_FU_180 ((ROUNDUP(180,8))/8) /* 180 bits */
241 static int
242 ipxotp_status(void *oh)
244 otpinfo_t *oi = (otpinfo_t *)oh;
245 return (int)(oi->status);
248 /* Return size in bytes */
249 static int
250 ipxotp_size(void *oh)
252 otpinfo_t *oi = (otpinfo_t *)oh;
253 return (int)oi->wsize * 2;
256 static uint16
257 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
259 otpinfo_t *oi;
261 oi = (otpinfo_t *)oh;
263 ASSERT(wn < oi->wsize);
264 ASSERT(cc != NULL);
266 return R_REG(oi->osh, &cc->sromotp[wn]);
269 static uint16
270 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
272 otpinfo_t *oi = (otpinfo_t *)oh;
273 uint k, row, col;
274 uint32 otpp, st;
276 row = off / oi->cols;
277 col = off % oi->cols;
279 otpp = OTPP_START_BUSY |
280 ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
281 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
282 ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
283 OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x",
284 __FUNCTION__, off, row, col, otpp));
285 W_REG(oi->osh, &cc->otpprog, otpp);
287 for (k = 0;
288 ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
289 k ++)
291 if (k >= OTPP_TRIES) {
292 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
293 return 0xffff;
295 if (st & OTPP_READERR) {
296 OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, off));
297 return 0xffff;
299 st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
301 OTP_DBG((" => %d\n", st));
302 return (int)st;
306 /* Calculate max HW/SW region byte size by substracting fuse region and checksum size,
307 * osizew is oi->wsize (OTP size - GU size) in words
309 static int
310 ipxotp_max_rgnsz(otpinfo_t *oi)
312 int osizew = oi->wsize;
313 int ret = 0;
314 uint16 checksum;
315 uint idx;
316 chipcregs_t *cc;
318 idx = si_coreidx(oi->sih);
319 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
320 ASSERT(cc != NULL);
322 checksum = OTP_SZ_CHECKSUM;
324 /* for new chips, fusebit is available from cc register */
325 if (oi->sih->ccrev >= 35) {
326 oi->fusebits = R_REG(oi->osh, &cc->otplayoutextension) & OTPLAYOUTEXT_FUSE_MASK;
329 si_setcoreidx(oi->sih, idx);
331 switch (CHIPID(oi->sih->chip)) {
332 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
333 oi->fusebits = OTP_SZ_FU_288;
334 break;
335 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
336 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID:
337 case BCM43226_CHIP_ID: case BCM43420_CHIP_ID:
338 oi->fusebits = OTP_SZ_FU_72;
339 break;
340 case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID:
341 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
342 oi->fusebits = OTP_SZ_FU_324;
343 break;
344 case BCM4325_CHIP_ID:
345 case BCM5356_CHIP_ID:
346 oi->fusebits = OTP_SZ_FU_216;
347 break;
348 case BCM4336_CHIP_ID:
349 case BCM43362_CHIP_ID:
350 oi->fusebits = OTP_SZ_FU_144;
351 break;
352 case BCM4313_CHIP_ID:
353 oi->fusebits = OTP_SZ_FU_72;
354 break;
355 case BCM4330_CHIP_ID:
356 oi->fusebits = OTP_SZ_FU_144;
357 break;
358 case BCM4319_CHIP_ID:
359 oi->fusebits = OTP_SZ_FU_180;
360 break;
361 case BCM4331_CHIP_ID:
362 case BCM43431_CHIP_ID:
363 oi->fusebits = OTP_SZ_FU_72;
364 break;
365 case BCM43131_CHIP_ID:
366 case BCM43227_CHIP_ID:
367 case BCM43228_CHIP_ID:
368 case BCM43428_CHIP_ID:
369 oi->fusebits = OTP_SZ_FU_72;
370 break;
371 default:
372 ASSERT(0); /* Don't konw about this chip */
375 ret = osizew*2 - oi->fusebits - checksum;
377 if (CHIPID(oi->sih->chip) == BCM4315_CHIP_ID) {
378 ret = OTP4315_SWREG_SZ;
381 OTP_MSG(("max region size %d bytes\n", ret));
382 return ret;
385 static void
386 BCMNMIATTACHFN(_ipxotp_init)(otpinfo_t *oi, chipcregs_t *cc)
388 uint k;
389 uint32 otpp, st;
391 /* record word offset of General Use Region for various chipcommon revs */
392 if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 || oi->sih->ccrev == 27) {
393 oi->otpgu_base = REVA4_OTPGU_BASE;
394 } else if (oi->sih->ccrev == 36) {
395 /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
396 if (oi->wsize >= 128)
397 oi->otpgu_base = REVB8_OTPGU_BASE;
398 else
399 oi->otpgu_base = REV36_OTPGU_BASE;
400 } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
401 oi->otpgu_base = REVB8_OTPGU_BASE;
402 } else {
403 OTP_ERR(("%s: chipc rev %d not supported\n", __FUNCTION__, oi->sih->ccrev));
406 /* First issue an init command so the status is up to date */
407 otpp = OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
409 OTP_DBG(("%s: otpp = 0x%x", __FUNCTION__, otpp));
410 W_REG(oi->osh, &cc->otpprog, otpp);
411 for (k = 0;
412 ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
413 k ++)
415 if (k >= OTPP_TRIES) {
416 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
417 return;
420 /* Read OTP lock bits and subregion programmed indication bits */
421 oi->status = R_REG(oi->osh, &cc->otpstatus);
423 if ((CHIPID(oi->sih->chip) == BCM43222_CHIP_ID) ||
424 (CHIPID(oi->sih->chip) == BCM43420_CHIP_ID) ||
425 (CHIPID(oi->sih->chip) == BCM43111_CHIP_ID) ||
426 (CHIPID(oi->sih->chip) == BCM43112_CHIP_ID) ||
427 (CHIPID(oi->sih->chip) == BCM43224_CHIP_ID) ||
428 (CHIPID(oi->sih->chip) == BCM43225_CHIP_ID) ||
429 (CHIPID(oi->sih->chip) == BCM43421_CHIP_ID) ||
430 (CHIPID(oi->sih->chip) == BCM43226_CHIP_ID) ||
431 (CHIPID(oi->sih->chip) == BCM43236_CHIP_ID) ||
432 (CHIPID(oi->sih->chip) == BCM43235_CHIP_ID) ||
433 (CHIPID(oi->sih->chip) == BCM43234_CHIP_ID) ||
434 (CHIPID(oi->sih->chip) == BCM43238_CHIP_ID) ||
435 (CHIPID(oi->sih->chip) == BCM43237_CHIP_ID) ||
436 (CHIPID(oi->sih->chip) == BCM4331_CHIP_ID) ||
437 (CHIPID(oi->sih->chip) == BCM43431_CHIP_ID) ||
438 0) {
439 if (nvram_match("boardtype", "0xa4cf") && nvram_match("boardrev", "0x1102")) {
440 // dd-wrt fix:
441 // skip this code on Belkin f7d4302 - crashes 2nd radio, reason unknown
442 printk(KERN_EMERG "Belkin f7d4302\n");
444 else {
445 uint32 p_bits;
446 p_bits = (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & OTPGU_P_MSK)
447 >> OTPGU_P_SHIFT;
448 oi->status |= (p_bits << OTPS_GUP_SHIFT);
451 OTP_DBG(("%s: status 0x%x\n", __FUNCTION__, oi->status));
454 * h/w region base and fuse region limit are fixed to the top and
455 * the bottom of the general use region. Everything else can be flexible.
457 oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
458 oi->hwlim = oi->wsize;
459 if (oi->status & OTPS_GUP_HW) {
460 OTP_DBG(("%s: hw region programmed\n", __FUNCTION__));
461 oi->hwlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
462 oi->swbase = oi->hwlim;
463 } else {
464 oi->hwlim = ipxotp_max_rgnsz(oi) / 2;
465 oi->swbase = oi->hwbase;
468 /* subtract fuse and checksum from beginning */
469 oi->swlim = ipxotp_max_rgnsz(oi) / 2;
471 if (oi->status & OTPS_GUP_SW) {
472 OTP_DBG(("%s: sw region programmed\n", __FUNCTION__));
473 oi->swlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
474 oi->fbase = oi->swlim;
476 else
477 oi->fbase = oi->swbase;
479 oi->flim = oi->wsize;
481 OTP_DBG(("%s: OTP limits---\n"
482 "hwbase %d/%d hwlim %d/%d\n"
483 "swbase %d/%d swlim %d/%d\n"
484 "fbase %d/%d flim %d/%d\n", __FUNCTION__,
485 oi->hwbase, oi->hwbase * 16, oi->hwlim, oi->hwlim * 16,
486 oi->swbase, oi->swbase * 16, oi->swlim, oi->swlim * 16,
487 oi->fbase, oi->fbase * 16, oi->flim, oi->flim * 16));
490 static void *
491 BCMNMIATTACHFN(ipxotp_init)(si_t *sih)
493 uint idx;
494 chipcregs_t *cc;
495 otpinfo_t *oi;
497 OTP_MSG(("%s: Use IPX OTP controller\n", __FUNCTION__));
499 /* Make sure we're running IPX OTP */
500 ASSERT(OTPTYPE_IPX(sih->ccrev));
501 if (!OTPTYPE_IPX(sih->ccrev))
502 return NULL;
504 /* Make sure OTP is not disabled */
505 if (si_is_otp_disabled(sih)) {
506 OTP_MSG(("%s: OTP is disabled\n", __FUNCTION__));
507 #if !defined(WLTEST)
508 return NULL;
509 #endif
512 /* Make sure OTP is powered up */
513 if (!si_is_otp_powered(sih)) {
514 OTP_ERR(("%s: OTP is powered down\n", __FUNCTION__));
515 return NULL;
518 oi = &otpinfo;
520 /* Check for otp size */
521 switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
522 case 0:
523 /* Nothing there */
524 OTP_ERR(("%s: no OTP\n", __FUNCTION__));
525 return NULL;
526 case 1: /* 32x64 */
527 oi->rows = 32;
528 oi->cols = 64;
529 oi->wsize = 128;
530 break;
531 case 2: /* 64x64 */
532 oi->rows = 64;
533 oi->cols = 64;
534 oi->wsize = 256;
535 break;
536 case 5: /* 96x64 */
537 oi->rows = 96;
538 oi->cols = 64;
539 oi->wsize = 384;
540 break;
541 case 7: /* 16x64 */ /* 1024 bits */
542 oi->rows = 16;
543 oi->cols = 64;
544 oi->wsize = 64;
545 break;
546 default:
547 /* Don't know the geometry */
548 OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__));
549 return NULL;
552 OTP_MSG(("%s: rows %u cols %u wsize %u\n", __FUNCTION__, oi->rows, oi->cols, oi->wsize));
554 #ifdef BCMNVRAMW
555 /* Initialize OTP redundancy control blocks */
556 if (sih->ccrev == 21 || sih->ccrev == 24) {
557 uint16 offset[] = {64, 79, 94, 109, 128, 143, 158, 173};
558 bcopy(offset, &oi->rde_cb.offset, sizeof(offset));
559 oi->rde_cb.offsets = ARRAYSIZE(offset);
560 oi->rde_cb.width = 15;
561 oi->rde_cb.val_shift = 11;
562 oi->rde_cb.stat_shift = 16;
564 else if (sih->ccrev == 27) {
565 uint16 offset[] = {128, 143, 158, 173};
566 bcopy(offset, &oi->rde_cb.offset, sizeof(offset));
567 oi->rde_cb.offsets = ARRAYSIZE(offset);
568 oi->rde_cb.width = 15;
569 oi->rde_cb.val_shift = 11;
570 oi->rde_cb.stat_shift = 20;
572 else {
573 uint16 offset[] = {141, 158, 175, 205, 222, 239, 269, 286, 303};
574 bcopy(offset, &oi->rde_cb.offset, sizeof(offset));
575 oi->rde_cb.offsets = ARRAYSIZE(offset);
576 oi->rde_cb.width = 17;
577 oi->rde_cb.val_shift = 13;
578 oi->rde_cb.stat_shift = 16;
580 ASSERT(oi->rde_cb.offsets <= MAXNUMRDES);
581 #endif /* BCMNVRAMW */
583 /* Retrieve OTP region info */
584 idx = si_coreidx(sih);
585 cc = si_setcoreidx(sih, SI_CC_IDX);
586 ASSERT(cc != NULL);
588 _ipxotp_init(oi, cc);
590 si_setcoreidx(sih, idx);
592 return (void *)oi;
595 static int
596 ipxotp_read_region(void *oh, int region, uint16 *data, uint *wlen)
598 otpinfo_t *oi = (otpinfo_t *)oh;
599 uint idx;
600 chipcregs_t *cc;
601 uint base, i, sz;
603 /* Validate region selection */
604 switch (region) {
605 case OTP_HW_RGN:
606 sz = (uint)oi->hwlim - oi->hwbase;
607 if (!(oi->status & OTPS_GUP_HW)) {
608 OTP_ERR(("%s: h/w region not programmed\n", __FUNCTION__));
609 *wlen = sz;
610 return BCME_NOTFOUND;
612 if (*wlen < sz) {
613 OTP_ERR(("%s: buffer too small, should be at least %u\n",
614 __FUNCTION__, oi->hwlim - oi->hwbase));
615 *wlen = sz;
616 return BCME_BUFTOOSHORT;
618 base = oi->hwbase;
619 break;
620 case OTP_SW_RGN:
621 sz = ((uint)oi->swlim - oi->swbase);
622 if (!(oi->status & OTPS_GUP_SW)) {
623 OTP_ERR(("%s: s/w region not programmed\n", __FUNCTION__));
624 *wlen = sz;
625 return BCME_NOTFOUND;
627 if (*wlen < sz) {
628 OTP_ERR(("%s: buffer too small should be at least %u\n",
629 __FUNCTION__, oi->swlim - oi->swbase));
630 *wlen = sz;
631 return BCME_BUFTOOSHORT;
633 base = oi->swbase;
634 break;
635 case OTP_CI_RGN:
636 sz = OTPGU_CI_SZ;
637 if (!(oi->status & OTPS_GUP_CI)) {
638 OTP_ERR(("%s: chipid region not programmed\n", __FUNCTION__));
639 *wlen = sz;
640 return BCME_NOTFOUND;
642 if (*wlen < sz) {
643 OTP_ERR(("%s: buffer too small, should be at least %u\n",
644 __FUNCTION__, OTPGU_CI_SZ));
645 *wlen = sz;
646 return BCME_BUFTOOSHORT;
648 base = oi->otpgu_base + OTPGU_CI_OFF;
649 break;
650 case OTP_FUSE_RGN:
651 sz = (uint)oi->flim - oi->fbase;
652 if (!(oi->status & OTPS_GUP_FUSE)) {
653 OTP_ERR(("%s: fuse region not programmed\n", __FUNCTION__));
654 *wlen = sz;
655 return BCME_NOTFOUND;
657 if (*wlen < sz) {
658 OTP_ERR(("%s: buffer too small, should be at least %u\n",
659 __FUNCTION__, oi->flim - oi->fbase));
660 *wlen = sz;
661 return BCME_BUFTOOSHORT;
663 base = oi->fbase;
664 break;
665 case OTP_ALL_RGN:
666 sz = ((uint)oi->flim - oi->hwbase);
667 if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
668 OTP_ERR(("%s: h/w & s/w region not programmed\n", __FUNCTION__));
669 *wlen = sz;
670 return BCME_NOTFOUND;
672 if (*wlen < sz) {
673 OTP_ERR(("%s: buffer too small, should be at least %u\n",
674 __FUNCTION__, oi->hwlim - oi->hwbase));
675 *wlen = sz;
676 return BCME_BUFTOOSHORT;
678 base = oi->hwbase;
679 break;
680 default:
681 OTP_ERR(("%s: reading region %d is not supported\n", __FUNCTION__, region));
682 return BCME_BADARG;
685 idx = si_coreidx(oi->sih);
686 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
687 ASSERT(cc != NULL);
689 /* Read the data */
690 for (i = 0; i < sz; i ++)
691 data[i] = ipxotp_otpr(oh, cc, base + i);
693 si_setcoreidx(oi->sih, idx);
694 *wlen = sz;
695 return 0;
698 static int
699 ipxotp_read_word(void *oh, uint wn, uint16 *data)
701 otpinfo_t *oi = (otpinfo_t *)oh;
702 uint idx;
703 chipcregs_t *cc;
705 idx = si_coreidx(oi->sih);
706 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
707 ASSERT(cc != NULL);
709 /* Read the data */
710 *data = ipxotp_otpr(oh, cc, wn);
712 si_setcoreidx(oi->sih, idx);
713 return 0;
716 static int
717 ipxotp_nvread(void *oh, char *data, uint *len)
719 return BCME_UNSUPPORTED;
722 #ifdef BCMNVRAMW
723 static int
724 ipxotp_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off)
726 uint k, row, col;
727 uint32 otpp, st;
729 row = off / oi->cols;
730 col = off % oi->cols;
732 otpp = OTPP_START_BUSY |
733 ((1 << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) |
734 ((OTPPOC_BIT_PROG << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
735 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
736 ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
737 OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n",
738 __FUNCTION__, off, row, col, otpp));
740 W_REG(oi->osh, &cc->otpprog, otpp);
742 for (k = 0;
743 ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
744 k ++)
746 if (k >= OTPP_TRIES) {
747 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
748 return -1;
751 return 0;
755 static int
756 ipxotp_write_lock_bit(otpinfo_t *oi, chipcregs_t *cc, uint off)
758 uint k, row, col;
759 uint32 otpp, st;
761 row = off / oi->cols;
762 col = off % oi->cols;
764 otpp = OTPP_START_BUSY |
765 ((OTPPOC_ROW_LOCK << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
766 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
767 ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
768 OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n",
769 __FUNCTION__, off, row, col, otpp));
771 W_REG(oi->osh, &cc->otpprog, otpp);
773 for (k = 0;
774 ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
775 k ++)
777 if (k >= OTPP_TRIES) {
778 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
779 return -1;
782 return 0;
785 static int
786 ipxotp_otpwb16(otpinfo_t *oi, chipcregs_t *cc, int wn, uint16 data)
788 uint base, i;
789 int rc = 0;
791 base = wn * 16;
792 for (i = 0; i < 16; i++) {
793 if (data & (1 << i)) {
794 if ((rc = ipxotp_write_bit(oi, cc, base + i)))
795 break;
799 return rc;
802 /* Write OTP redundancy entry:
803 * rde - redundancy entry index (-ve for "next")
804 * bit - bit offset
805 * val - bit value
808 ipxotp_write_rde(void *oh, int rde, uint bit, uint val)
810 otpinfo_t *oi = (otpinfo_t *)oh;
811 uint idx;
812 chipcregs_t *cc;
813 uint i, temp;
815 #ifdef BCMCBG
816 if ((rde >= oi->rde_cb.offsets) || (bit >= oi->rows * oi->cols) || (val > 1))
817 return BCME_RANGE;
818 #endif
820 if (rde < 0) {
821 for (rde = 0; rde < oi->rde_cb.offsets - 1; rde++) {
822 if ((oi->status & (1 << (oi->rde_cb.stat_shift + rde))) == 0)
823 break;
825 OTP_MSG(("%s: Auto rde index %d\n", __FUNCTION__, rde));
828 if (oi->status & (1 << (oi->rde_cb.stat_shift + rde))) {
829 OTP_MSG(("%s: rde %d already in use, status 0x%08x\n", __FUNCTION__,
830 rde, oi->status));
831 return BCME_ERROR;
834 idx = si_coreidx(oi->sih);
835 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
836 ASSERT(cc != NULL);
838 temp = ~(~0 << oi->rde_cb.width) &
839 ((~0 << (oi->rde_cb.val_shift + 1)) | (val << oi->rde_cb.val_shift) | bit);
841 OTP_MSG(("%s: rde %d bit %d val %d bmp 0x%08x\n", __FUNCTION__, rde, bit, val, temp));
843 /* Enable Write */
844 OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
846 for (i = 0; i < oi->rde_cb.width; i ++) {
847 if (!(temp & (1 << i)))
848 continue;
849 ipxotp_write_bit(oi, cc, oi->rde_cb.offset[rde] + i);
852 /* Disable Write */
853 AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
855 si_otp_power(oi->sih, FALSE);
856 si_otp_power(oi->sih, TRUE);
857 _ipxotp_init(oi, cc);
859 si_setcoreidx(oi->sih, idx);
860 return BCME_OK;
863 /* Set up redundancy entries for the specified bits */
864 static int
865 ipxotp_fix_word16(void *oh, uint wn, uint16 mask, uint16 val)
867 otpinfo_t *oi;
868 uint bit;
869 int rc = 0;
871 oi = (otpinfo_t *)oh;
873 ASSERT(oi != NULL);
874 ASSERT(wn < oi->wsize);
876 for (bit = wn * 16; mask; bit++, mask >>= 1, val >>= 1) {
877 if (mask & 1) {
878 if ((rc = ipxotp_write_rde(oi, -1, bit, val & 1)))
879 break;
883 return rc;
886 static int
887 ipxotp_check_word16(void *oh, chipcregs_t *cc, uint wn, uint16 val)
889 otpinfo_t *oi = (otpinfo_t *)oh;
890 uint16 word = ipxotp_otpr(oi, cc, wn);
891 int rc = 0;
893 if ((word ^= val)) {
894 OTP_MSG(("%s: word %d is 0x%04x, wanted 0x%04x, fixing...\n",
895 __FUNCTION__, wn, (word ^ val), val));
896 if ((rc = ipxotp_fix_word16(oi, wn, word, val))) {
897 OTP_ERR(("FAILED, ipxotp_fix_word16 returns %d\n", rc));
898 /* Fatal error, unfixable. MFGC will have to fail. Board
899 * needs to be discarded!!
901 return BCME_NORESOURCE;
905 return BCME_OK;
908 /* expects the caller to disable interrupts before calling this routine */
909 static int
910 ipxotp_write_region(void *oh, int region, uint16 *data, uint wlen)
912 otpinfo_t *oi = (otpinfo_t *)oh;
913 uint idx;
914 chipcregs_t *cc;
915 uint base, i;
916 int otpgu_bit_base;
917 bool rewrite = FALSE;
918 int rc = 0;
919 uint16 *origdata = NULL;
921 otpgu_bit_base = oi->otpgu_base * 16;
923 /* Validate region selection */
924 switch (region) {
925 case OTP_HW_RGN:
926 if (wlen > (uint)(oi->hwlim - oi->hwbase)) {
927 OTP_ERR(("%s: wlen %u exceeds OTP h/w region limit %u\n",
928 __FUNCTION__, wlen, oi->hwlim - oi->hwbase));
929 return BCME_BUFTOOLONG;
931 rewrite = !!(oi->status & OTPS_GUP_HW);
932 base = oi->hwbase;
933 break;
934 case OTP_SW_RGN:
935 if (wlen > (uint)(oi->swlim - oi->swbase)) {
936 OTP_ERR(("%s: wlen %u exceeds OTP s/w region limit %u\n",
937 __FUNCTION__, wlen, oi->swlim - oi->swbase));
938 return BCME_BUFTOOLONG;
940 rewrite = !!(oi->status & OTPS_GUP_SW);
941 base = oi->swbase;
942 break;
943 case OTP_CI_RGN:
944 if (oi->status & OTPS_GUP_CI) {
945 OTP_ERR(("%s: chipid region has been programmed\n", __FUNCTION__));
946 return BCME_ERROR;
948 if (wlen > OTPGU_CI_SZ) {
949 OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n",
950 __FUNCTION__, wlen, OTPGU_CI_SZ));
951 return BCME_BUFTOOLONG;
953 if ((wlen == OTPGU_CI_SZ) && (data[OTPGU_CI_SZ - 1] & OTPGU_P_MSK) != 0) {
954 OTP_ERR(("%s: subregion programmed bits not zero\n", __FUNCTION__));
955 return BCME_BADARG;
957 base = oi->otpgu_base + OTPGU_CI_OFF;
958 break;
959 case OTP_FUSE_RGN:
960 if (oi->status & OTPS_GUP_FUSE) {
961 OTP_ERR(("%s: fuse region has been programmed\n", __FUNCTION__));
962 return BCME_ERROR;
964 if (wlen > (uint)(oi->flim - oi->fbase)) {
965 OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n",
966 __FUNCTION__, wlen, oi->flim - oi->fbase));
967 return BCME_BUFTOOLONG;
969 base = oi->flim - wlen;
970 break;
971 default:
972 OTP_ERR(("%s: writing region %d is not supported\n", __FUNCTION__, region));
973 return BCME_ERROR;
976 idx = si_coreidx(oi->sih);
977 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
978 ASSERT(cc != NULL);
980 /* Check for conflict; Since some bits might be programmed at ATE time, we need to
981 * avoid redundancy by clearing already written bits, but copy original for verification.
983 if ((origdata = (uint16*)MALLOC(oi->osh, wlen * 2)) == NULL) {
984 rc = BCME_NOMEM;
985 goto exit;
987 for (i = 0; i < wlen; i++) {
988 origdata[i] = data[i];
989 data[i] = ipxotp_otpr(oi, cc, base + i);
990 if (data[i] & ~origdata[i]) {
991 OTP_ERR(("%s: %s region: word %d incompatible (0x%04x->0x%04x)\n",
992 __FUNCTION__, HWSW_RGN(region), i, data[i], origdata[i]));
993 rc = BCME_BADARG;
994 goto exit;
996 data[i] ^= origdata[i];
998 OTP_MSG(("%s: writing new bits in %s region\n", __FUNCTION__, HWSW_RGN(region)));
1000 /* Enable Write */
1001 OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
1003 /* Write the data */
1004 for (i = 0; i < wlen; i++) {
1005 ipxotp_otpwb16(oi, cc, base + i, data[i]);
1008 /* One time set region flag: Update boundary/flag in memory and in OTP */
1009 if (!rewrite) {
1010 switch (region) {
1011 case OTP_HW_RGN:
1012 ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, (base + i) * 16);
1013 ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_HWP_OFF);
1014 break;
1015 case OTP_SW_RGN:
1016 /* Write HW region limit as well */
1017 ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, base * 16);
1018 /* write max swlim(covert to bits) to the sw/fuse boundary */
1019 ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, oi->swlim * 16);
1020 ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_SWP_OFF);
1021 break;
1022 case OTP_CI_RGN:
1023 ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_CIP_OFF);
1024 /* Also set the OTPGU_CIP_MSK bit in the input so verification
1025 * doesn't fail
1027 if (wlen >= OTPGU_CI_SZ)
1028 data[OTPGU_CI_SZ - 1] |= OTPGU_CIP_MSK;
1029 break;
1030 case OTP_FUSE_RGN:
1031 ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, base * 16);
1032 ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_FUSEP_OFF);
1033 break;
1037 /* Disable Write */
1038 AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
1040 /* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */
1041 si_otp_power(oi->sih, FALSE);
1042 si_otp_power(oi->sih, TRUE);
1044 /* Check and fix for region size and region programmed bits */
1045 if (!rewrite) {
1046 uint16 boundary_off = 0, boundary_val = 0;
1047 uint16 programmed_off = 0;
1048 uint16 bit = 0;
1050 switch (region) {
1051 case OTP_HW_RGN:
1052 boundary_off = OTPGU_HSB_OFF;
1053 boundary_val = (base + i) * 16;
1054 programmed_off = OTPGU_HWP_OFF;
1055 break;
1056 case OTP_SW_RGN:
1057 /* Also write 0 to HW region boundary */
1058 if ((rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF,
1059 base * 16)))
1060 goto exit;
1061 boundary_off = OTPGU_SFB_OFF;
1062 boundary_val = oi->swlim * 16;
1063 programmed_off = OTPGU_SWP_OFF;
1064 break;
1065 case OTP_CI_RGN:
1066 /* No CI region boundary */
1067 programmed_off = OTPGU_CIP_OFF;
1068 break;
1069 case OTP_FUSE_RGN:
1070 boundary_off = OTPGU_SFB_OFF;
1071 boundary_val = base * 16;
1072 programmed_off = OTPGU_FUSEP_OFF;
1073 break;
1076 /* Do the actual checking and return BCME_NORESOURCE if we cannot fix */
1077 if ((region != OTP_CI_RGN) &&
1078 (rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + boundary_off,
1079 boundary_val))) {
1080 goto exit;
1083 if ((bit = ipxotp_read_bit(oh, cc, otpgu_bit_base + programmed_off)) == 0xffff) {
1084 OTP_ERR(("\n%s: FAILED bit %d reads %d\n", __FUNCTION__, otpgu_bit_base +
1085 programmed_off, bit));
1086 goto exit;
1087 } else if (bit == 0) { /* error detected, fix it */
1088 OTP_ERR(("\n%s: FAILED bit %d reads %d, fixing\n", __FUNCTION__,
1089 otpgu_bit_base + programmed_off, bit));
1090 if ((rc = ipxotp_write_rde(oi, -1, otpgu_bit_base + programmed_off, 1))) {
1091 OTP_ERR(("\n%s: cannot fix, ipxotp_write_rde returns %d\n",
1092 __FUNCTION__, rc));
1093 goto exit;
1098 /* Update status, apply WAR */
1099 _ipxotp_init(oi, cc);
1101 /* Recover original data... */
1102 if (origdata)
1103 bcopy(origdata, data, wlen * 2);
1105 /* ...so we can verify and fix where possible */
1106 for (i = 0; i < wlen; i++) {
1107 if ((rc = ipxotp_check_word16(oi, cc, base + i, data[i])))
1108 goto exit;
1111 exit:
1112 if (origdata)
1113 MFREE(oi->osh, origdata, wlen * 2);
1115 si_setcoreidx(oi->sih, idx);
1116 return rc;
1119 static int
1120 ipxotp_write_word(void *oh, uint wn, uint16 data)
1122 otpinfo_t *oi = (otpinfo_t *)oh;
1123 int rc = 0;
1124 uint16 origdata;
1125 uint idx;
1126 chipcregs_t *cc;
1128 idx = si_coreidx(oi->sih);
1129 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1130 ASSERT(cc != NULL);
1132 /* Check for conflict */
1133 origdata = data;
1134 data = ipxotp_otpr(oi, cc, wn);
1135 if (data & ~origdata) {
1136 OTP_ERR(("%s: word %d incompatible (0x%04x->0x%04x)\n",
1137 __FUNCTION__, wn, data, origdata));
1138 rc = BCME_BADARG;
1139 goto exit;
1141 data ^= origdata;
1143 /* Enable Write */
1144 OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
1146 rc = ipxotp_otpwb16(oi, cc, wn, data);
1148 /* Disable Write */
1149 AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
1151 data = origdata;
1152 if ((rc = ipxotp_check_word16(oi, cc, wn, data)))
1153 goto exit;
1154 exit:
1155 si_setcoreidx(oi->sih, idx);
1156 return rc;
1159 static int
1160 ipxotp_cis_append_region(si_t *sih, int region, char *vars, int count)
1162 uint8 *cis;
1163 osl_t *osh;
1164 uint sz = OTP_SZ_MAX/2; /* size in words */
1165 int rc = 0;
1166 bool newchip = FALSE;
1168 ASSERT(region == OTP_HW_RGN || region == OTP_SW_RGN);
1170 osh = si_osh(sih);
1171 if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) {
1172 return BCME_ERROR;
1175 bzero(cis, OTP_SZ_MAX);
1177 rc = otp_read_region(sih, region, (uint16 *)cis, &sz);
1178 newchip = (rc == BCME_NOTFOUND) ? TRUE : FALSE;
1179 if ((rc != 0) && (rc != BCME_NOTFOUND)) {
1180 return BCME_ERROR;
1182 rc = 0;
1184 /* zero count for read, non-zero count for write */
1185 if (count) {
1186 int i = 0, newlen = 0;
1188 if (newchip) {
1189 int termw_len = 0; /* length of termination word */
1191 /* convert halfwords to bytes offset */
1192 newlen = sz * 2;
1194 if ((CHIPID(sih->chip) == BCM4322_CHIP_ID) ||
1195 (CHIPID(sih->chip) == BCM43231_CHIP_ID) ||
1196 (CHIPID(sih->chip) == BCM4315_CHIP_ID) ||
1197 (CHIPID(sih->chip) == BCM4319_CHIP_ID)) {
1198 /* bootloader WAR, refer to above twiki link */
1199 cis[newlen-1] = 0x00;
1200 cis[newlen-2] = 0xff;
1201 cis[newlen-3] = 0x00;
1202 cis[newlen-4] = 0xff;
1203 cis[newlen-5] = 0xff;
1204 cis[newlen-6] = 0x1;
1205 cis[newlen-7] = 0x2;
1206 termw_len = 7;
1207 } else {
1208 cis[newlen-1] = 0xff;
1209 cis[newlen-2] = 0xff;
1210 termw_len = 2;
1213 if (count >= newlen - termw_len) {
1214 OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", newlen, count));
1215 rc = BCME_BUFTOOLONG;
1217 } else {
1218 int end = 0;
1220 /* Walk through the leading zeros (could be 0 or 8 bytes for now) */
1221 for (i = 0; i < (int)sz*2; i++)
1222 if (cis[i] != 0)
1223 break;
1225 /* Find the place to append */
1226 for (; i < (int)sz*2; i++) {
1227 if (cis[i] == 0)
1228 break;
1229 i += ((int)cis[i+1] + 1);
1232 for (end = i; end < (int)sz*2; end++) {
1233 if (cis[end] != 0)
1234 break;
1237 newlen = i + count;
1238 if (newlen & 1) /* make it even-sized buffer */
1239 newlen++;
1241 if (newlen >= (end - 1)) {
1242 OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", end-i, count));
1243 rc = BCME_BUFTOOLONG;
1247 /* copy the buffer */
1248 memcpy(&cis[i], vars, count);
1249 #ifdef BCMNVRAMW
1250 /* Write the buffer back */
1251 if (!rc)
1252 rc = otp_write_region(sih, region, (uint16*)cis, newlen/2);
1254 /* Print the buffer */
1255 OTP_MSG(("Buffer of size %d bytes to write:\n", newlen));
1256 for (i = 0; i < newlen; i++) {
1257 OTP_DBG(("%02x ", cis[i] & 0xff));
1258 if ((i % 16) == 15) {
1259 OTP_DBG(("\n"));
1262 OTP_MSG(("\n"));
1263 #endif /* BCMNVRAMW */
1266 if (cis)
1267 MFREE(osh, cis, OTP_SZ_MAX);
1269 return (rc);
1272 /* No need to lock for IPXOTP */
1273 static int
1274 ipxotp_lock(void *oh)
1276 uint idx;
1277 chipcregs_t *cc;
1278 otpinfo_t *oi = (otpinfo_t *)oh;
1279 int err = 0, rc = 0;
1281 idx = si_coreidx(oi->sih);
1282 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1283 ASSERT(cc != NULL);
1285 /* Enable Write */
1286 OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
1288 err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW1_LOC_OFF);
1289 if (err) {
1290 OTP_ERR(("fail to lock ROW1\n"));
1291 rc = -1;
1293 err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW2_LOC_OFF);
1294 if (err) {
1295 OTP_ERR(("fail to lock ROW2\n"));
1296 rc = -2;
1298 err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_RD_LOC_OFF);
1299 if (err) {
1300 OTP_ERR(("fail to lock RD\n"));
1301 rc = -3;
1303 err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_GU_LOC_OFF);
1304 if (err) {
1305 OTP_ERR(("fail to lock GU\n"));
1306 rc = -4;
1309 /* Disable Write */
1310 AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
1312 /* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */
1313 si_otp_power(oi->sih, FALSE);
1314 si_otp_power(oi->sih, TRUE);
1316 /* Update status, apply WAR */
1317 _ipxotp_init(oi, cc);
1318 return rc;
1321 static int
1322 ipxotp_nvwrite(void *oh, uint16 *data, uint wlen)
1324 return -1;
1326 #endif /* BCMNVRAMW */
1328 #if defined(WLTEST)
1329 static uint16
1330 ipxotp_otprb16(void *oh, chipcregs_t *cc, uint wn)
1332 uint base, i;
1333 uint16 val;
1334 uint16 bit;
1336 base = wn * 16;
1338 val = 0;
1339 for (i = 0; i < 16; i++) {
1340 if ((bit = ipxotp_read_bit(oh, cc, base + i)) == 0xffff)
1341 break;
1342 val = val | (bit << i);
1344 if (i < 16)
1345 val = 0xffff;
1347 return val;
1350 static int
1351 ipxotp_dump(void *oh, int arg, char *buf, uint size)
1353 otpinfo_t *oi = (otpinfo_t *)oh;
1354 chipcregs_t *cc;
1355 uint idx, i, count;
1356 uint16 val;
1357 struct bcmstrbuf b;
1359 idx = si_coreidx(oi->sih);
1360 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1361 ASSERT(cc != NULL);
1363 count = ipxotp_size(oh);
1365 bcm_binit(&b, buf, size);
1366 for (i = 0; i < count / 2; i++) {
1367 if (!(i % 4))
1368 bcm_bprintf(&b, "\n0x%04x:", 2 * i);
1369 if (arg == 0)
1370 val = ipxotp_otpr(oh, cc, i);
1371 else
1372 val = ipxotp_otprb16(oi, cc, i);
1373 bcm_bprintf(&b, " 0x%04x", val);
1375 bcm_bprintf(&b, "\n");
1377 si_setcoreidx(oi->sih, idx);
1379 return ((int)(b.buf - b.origbuf));
1381 #endif
1383 static otp_fn_t ipxotp_fn = {
1384 (otp_size_t)ipxotp_size,
1385 (otp_read_bit_t)ipxotp_read_bit,
1387 (otp_init_t)ipxotp_init,
1388 (otp_read_region_t)ipxotp_read_region,
1389 (otp_nvread_t)ipxotp_nvread,
1390 #ifdef BCMNVRAMW
1391 (otp_write_region_t)ipxotp_write_region,
1392 (otp_cis_append_region_t)ipxotp_cis_append_region,
1393 (otp_lock_t)ipxotp_lock,
1394 (otp_nvwrite_t)ipxotp_nvwrite,
1395 #endif /* BCMNVRAMW */
1397 #if defined(WLTEST)
1398 (otp_dump_t)ipxotp_dump,
1399 #endif
1401 (otp_status_t)ipxotp_status,
1402 #ifdef BCMNVRAMW
1403 (otp_write_word_t)ipxotp_write_word,
1404 #endif /* BCMNVRAMW */
1405 (otp_read_word_t)ipxotp_read_word,
1408 #endif /* BCMIPXOTP */
1412 * HND OTP Code
1414 * Exported functions:
1415 * hndotp_status()
1416 * hndotp_size()
1417 * hndotp_init()
1418 * hndotp_read_bit()
1419 * hndotp_read_region()
1420 * hndotp_read_word()
1421 * hndotp_nvread()
1422 * hndotp_write_region()
1423 * hndotp_cis_append_region()
1424 * hndotp_lock()
1425 * hndotp_nvwrite()
1426 * hndotp_dump()
1428 * HND internal functions:
1429 * hndotp_otpr()
1430 * hndotp_otproff()
1431 * hndotp_write_bit()
1432 * hndotp_write_word()
1433 * hndotp_valid_rce()
1434 * hndotp_write_rce()
1435 * hndotp_write_row()
1436 * hndotp_otprb16()
1440 #ifdef BCMHNDOTP
1442 /* Fields in otpstatus */
1443 #define OTPS_PROGFAIL 0x80000000
1444 #define OTPS_PROTECT 0x00000007
1445 #define OTPS_HW_PROTECT 0x00000001
1446 #define OTPS_SW_PROTECT 0x00000002
1447 #define OTPS_CID_PROTECT 0x00000004
1448 #define OTPS_RCEV_MSK 0x00003f00
1449 #define OTPS_RCEV_SHIFT 8
1451 /* Fields in the otpcontrol register */
1452 #define OTPC_RECWAIT 0xff000000
1453 #define OTPC_PROGWAIT 0x00ffff00
1454 #define OTPC_PRW_SHIFT 8
1455 #define OTPC_MAXFAIL 0x00000038
1456 #define OTPC_VSEL 0x00000006
1457 #define OTPC_SELVL 0x00000001
1459 /* OTP regions (Word offsets from otp size) */
1460 #define OTP_SWLIM_OFF (-4)
1461 #define OTP_CIDBASE_OFF 0
1462 #define OTP_CIDLIM_OFF 4
1464 /* Predefined OTP words (Word offset from otp size) */
1465 #define OTP_BOUNDARY_OFF (-4)
1466 #define OTP_HWSIGN_OFF (-3)
1467 #define OTP_SWSIGN_OFF (-2)
1468 #define OTP_CIDSIGN_OFF (-1)
1469 #define OTP_CID_OFF 0
1470 #define OTP_PKG_OFF 1
1471 #define OTP_FID_OFF 2
1472 #define OTP_RSV_OFF 3
1473 #define OTP_LIM_OFF 4
1474 #define OTP_RD_OFF 4 /* Redundancy row starts here */
1475 #define OTP_RC0_OFF 28 /* Redundancy control word 1 */
1476 #define OTP_RC1_OFF 32 /* Redundancy control word 2 */
1477 #define OTP_RC_LIM_OFF 36 /* Redundancy control word end */
1479 #define OTP_HW_REGION OTPS_HW_PROTECT
1480 #define OTP_SW_REGION OTPS_SW_PROTECT
1481 #define OTP_CID_REGION OTPS_CID_PROTECT
1483 #if OTP_HW_REGION != OTP_HW_RGN
1484 #error "incompatible OTP_HW_RGN"
1485 #endif
1486 #if OTP_SW_REGION != OTP_SW_RGN
1487 #error "incompatible OTP_SW_RGN"
1488 #endif
1489 #if OTP_CID_REGION != OTP_CI_RGN
1490 #error "incompatible OTP_CI_RGN"
1491 #endif
1493 /* Redundancy entry definitions */
1494 #define OTP_RCE_ROW_SZ 6
1495 #define OTP_RCE_SIGN_MASK 0x7fff
1496 #define OTP_RCE_ROW_MASK 0x3f
1497 #define OTP_RCE_BITS 21
1498 #define OTP_RCE_SIGN_SZ 15
1499 #define OTP_RCE_BIT0 1
1501 #define OTP_WPR 4
1502 #define OTP_SIGNATURE 0x578a
1503 #define OTP_MAGIC 0x4e56
1505 static int
1506 hndotp_status(void *oh)
1508 otpinfo_t *oi = (otpinfo_t *)oh;
1509 return ((int)(oi->hwprot | oi->signvalid));
1512 static int
1513 hndotp_size(void *oh)
1515 otpinfo_t *oi = (otpinfo_t *)oh;
1516 return ((int)(oi->size));
1519 static uint16
1520 hndotp_otpr(void *oh, chipcregs_t *cc, uint wn)
1522 otpinfo_t *oi = (otpinfo_t *)oh;
1523 osl_t *osh;
1524 volatile uint16 *ptr;
1526 ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF));
1527 ASSERT(cc != NULL);
1529 osh = si_osh(oi->sih);
1531 ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP);
1532 return (R_REG(osh, &ptr[wn]));
1535 static uint16
1536 hndotp_otproff(void *oh, chipcregs_t *cc, int woff)
1538 otpinfo_t *oi = (otpinfo_t *)oh;
1539 osl_t *osh;
1540 volatile uint16 *ptr;
1542 ASSERT(woff >= (-((int)oi->size / 2)));
1543 ASSERT(woff < OTP_LIM_OFF);
1544 ASSERT(cc != NULL);
1546 osh = si_osh(oi->sih);
1548 ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP);
1550 return (R_REG(osh, &ptr[(oi->size / 2) + woff]));
1553 static uint16
1554 hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx)
1556 otpinfo_t *oi = (otpinfo_t *)oh;
1557 uint k, row, col;
1558 uint32 otpp, st;
1559 osl_t *osh;
1561 osh = si_osh(oi->sih);
1562 row = idx / 65;
1563 col = idx % 65;
1565 otpp = OTPP_START_BUSY | OTPP_READ |
1566 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
1567 (col & OTPP_COL_MASK);
1569 OTP_DBG(("%s: idx = %d, row = %d, col = %d, otpp = 0x%x", __FUNCTION__,
1570 idx, row, col, otpp));
1572 W_REG(osh, &cc->otpprog, otpp);
1573 st = R_REG(osh, &cc->otpprog);
1574 for (k = 0; ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
1575 st = R_REG(osh, &cc->otpprog);
1577 if (k >= OTPP_TRIES) {
1578 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
1579 return 0xffff;
1581 if (st & OTPP_READERR) {
1582 OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, idx));
1583 return 0xffff;
1585 st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
1586 OTP_DBG((" => %d\n", st));
1587 return (uint16)st;
1590 static void *
1591 BCMNMIATTACHFN(hndotp_init)(si_t *sih)
1593 uint idx;
1594 chipcregs_t *cc;
1595 otpinfo_t *oi;
1596 uint32 cap = 0, clkdiv, otpdiv = 0;
1597 void *ret = NULL;
1598 osl_t *osh;
1600 OTP_MSG(("%s: Use HND OTP controller\n", __FUNCTION__));
1601 oi = &otpinfo;
1603 idx = si_coreidx(sih);
1604 osh = si_osh(oi->sih);
1606 /* Check for otp */
1607 if ((cc = si_setcoreidx(sih, SI_CC_IDX)) != NULL) {
1608 cap = R_REG(osh, &cc->capabilities);
1609 if ((cap & CC_CAP_OTPSIZE) == 0) {
1610 /* Nothing there */
1611 goto out;
1614 /* As of right now, support only 4320a2, 4311a1 and 4312 */
1615 ASSERT((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22));
1616 if (!((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22)))
1617 return NULL;
1619 /* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is
1620 * 8 row (64 bytes) smaller
1622 oi->size = 1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT)
1623 + CC_CAP_OTPSIZE_BASE);
1624 if (oi->ccrev >= 18) {
1625 oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2);
1626 } else {
1627 OTP_ERR(("Negative otp size, shouldn't happen for programmed chip."));
1628 oi->size = 0;
1631 oi->hwprot = (int)(R_REG(osh, &cc->otpstatus) & OTPS_PROTECT);
1632 oi->boundary = -1;
1634 /* Check the region signature */
1635 if (hndotp_otproff(oi, cc, OTP_HWSIGN_OFF) == OTP_SIGNATURE) {
1636 oi->signvalid |= OTP_HW_REGION;
1637 oi->boundary = hndotp_otproff(oi, cc, OTP_BOUNDARY_OFF);
1640 if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE)
1641 oi->signvalid |= OTP_SW_REGION;
1643 if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE)
1644 oi->signvalid |= OTP_CID_REGION;
1646 /* Set OTP clkdiv for stability */
1647 if (oi->ccrev == 22)
1648 otpdiv = 12;
1650 if (otpdiv) {
1651 clkdiv = R_REG(osh, &cc->clkdiv);
1652 clkdiv = (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT);
1653 W_REG(osh, &cc->clkdiv, clkdiv);
1654 OTP_MSG(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
1656 OSL_DELAY(10);
1658 ret = (void *)oi;
1661 OTP_MSG(("%s: ccrev %d\tsize %d bytes\thwprot %x\tsignvalid %x\tboundary %x\n",
1662 __FUNCTION__, oi->ccrev, oi->size, oi->hwprot, oi->signvalid,
1663 oi->boundary));
1665 out: /* All done */
1666 si_setcoreidx(sih, idx);
1668 return ret;
1671 static int
1672 hndotp_read_region(void *oh, int region, uint16 *data, uint *wlen)
1674 otpinfo_t *oi = (otpinfo_t *)oh;
1675 uint32 idx, st;
1676 chipcregs_t *cc;
1677 int i;
1679 /* Only support HW region (no active chips use HND OTP SW region) */
1680 ASSERT(region == OTP_HW_REGION);
1682 OTP_MSG(("%s: region %x wlen %d\n", __FUNCTION__, region, *wlen));
1684 /* Region empty? */
1685 st = oi->hwprot | oi-> signvalid;
1686 if ((st & region) == 0)
1687 return BCME_NOTFOUND;
1689 *wlen = ((int)*wlen < oi->boundary/2) ? *wlen : (uint)oi->boundary/2;
1691 idx = si_coreidx(oi->sih);
1692 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1693 ASSERT(cc != NULL);
1695 for (i = 0; i < (int)*wlen; i++)
1696 data[i] = hndotp_otpr(oh, cc, i);
1698 si_setcoreidx(oi->sih, idx);
1700 return 0;
1703 static int
1704 hndotp_read_word(void *oh, uint wn, uint16 *data)
1706 otpinfo_t *oi = (otpinfo_t *)oh;
1707 uint32 idx;
1708 chipcregs_t *cc;
1710 idx = si_coreidx(oi->sih);
1711 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1712 ASSERT(cc != NULL);
1714 *data = hndotp_otpr(oh, cc, wn);
1716 si_setcoreidx(oi->sih, idx);
1717 return 0;
1720 static int
1721 hndotp_nvread(void *oh, char *data, uint *len)
1723 int rc = 0;
1724 otpinfo_t *oi = (otpinfo_t *)oh;
1725 uint32 base, bound, lim = 0, st;
1726 int i, chunk, gchunks, tsz = 0;
1727 uint32 idx;
1728 chipcregs_t *cc;
1729 uint offset;
1730 uint16 *rawotp = NULL;
1732 /* save the orig core */
1733 idx = si_coreidx(oi->sih);
1734 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1735 ASSERT(cc != NULL);
1737 st = hndotp_status(oh);
1738 if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) {
1739 OTP_ERR(("OTP not programmed\n"));
1740 rc = -1;
1741 goto out;
1744 /* Read the whole otp so we can easily manipulate it */
1745 lim = hndotp_size(oh);
1746 if (lim == 0) {
1747 OTP_ERR(("OTP size is 0\n"));
1748 rc = -1;
1749 goto out;
1751 if ((rawotp = MALLOC(si_osh(oi->sih), lim)) == NULL) {
1752 OTP_ERR(("Out of memory for rawotp\n"));
1753 rc = -2;
1754 goto out;
1756 for (i = 0; i < (int)(lim / 2); i++)
1757 rawotp[i] = hndotp_otpr(oh, cc, i);
1759 if ((st & OTP_HW_REGION) == 0) {
1760 OTP_ERR(("otp: hw region not written (0x%x)\n", st));
1762 /* This could be a programming failure in the first
1763 * chunk followed by one or more good chunks
1765 for (i = 0; i < (int)(lim / 2); i++)
1766 if (rawotp[i] == OTP_MAGIC)
1767 break;
1769 if (i < (int)(lim / 2)) {
1770 base = i;
1771 bound = (i * 2) + rawotp[i + 1];
1772 OTP_MSG(("otp: trying chunk at 0x%x-0x%x\n", i * 2, bound));
1773 } else {
1774 OTP_MSG(("otp: unprogrammed\n"));
1775 rc = -3;
1776 goto out;
1778 } else {
1779 bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF];
1781 /* There are two cases: 1) The whole otp is used as nvram
1782 * and 2) There is a hardware header followed by nvram.
1784 if (rawotp[0] == OTP_MAGIC) {
1785 base = 0;
1786 if (bound != rawotp[1])
1787 OTP_MSG(("otp: Bound 0x%x != chunk0 len 0x%x\n", bound,
1788 rawotp[1]));
1789 } else
1790 base = bound;
1793 /* Find and copy the data */
1795 chunk = 0;
1796 gchunks = 0;
1797 i = base / 2;
1798 offset = 0;
1799 while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) {
1800 int dsz, rsz = rawotp[i + 1];
1802 if (((i * 2) + rsz) >= (int)lim) {
1803 OTP_MSG((" bad chunk size, chunk %d, base 0x%x, size 0x%x\n",
1804 chunk, i * 2, rsz));
1805 /* Bad length, try to find another chunk anyway */
1806 rsz = 6;
1808 if (hndcrc16((uint8 *)&rawotp[i], rsz,
1809 CRC16_INIT_VALUE) == CRC16_GOOD_VALUE) {
1810 /* Good crc, copy the vars */
1811 OTP_MSG((" good chunk %d, base 0x%x, size 0x%x\n",
1812 chunk, i * 2, rsz));
1813 gchunks++;
1814 dsz = rsz - 6;
1815 tsz += dsz;
1816 if (offset + dsz >= *len) {
1817 OTP_MSG(("Out of memory for otp\n"));
1818 goto out;
1820 bcopy((char *)&rawotp[i + 2], &data[offset], dsz);
1821 offset += dsz;
1822 /* Remove extra null characters at the end */
1823 while (offset > 1 &&
1824 data[offset - 1] == 0 && data[offset - 2] == 0)
1825 offset --;
1826 i += rsz / 2;
1827 } else {
1828 /* bad length or crc didn't check, try to find the next set */
1829 OTP_MSG((" chunk %d @ 0x%x size 0x%x: bad crc, ",
1830 chunk, i * 2, rsz));
1831 if (rawotp[i + (rsz / 2)] == OTP_MAGIC) {
1832 /* Assume length is good */
1833 i += rsz / 2;
1834 } else {
1835 while (++i < (int)(lim / 2))
1836 if (rawotp[i] == OTP_MAGIC)
1837 break;
1839 if (i < (int)(lim / 2))
1840 OTP_MSG(("trying next base 0x%x\n", i * 2));
1841 else
1842 OTP_MSG(("no more chunks\n"));
1844 chunk++;
1847 OTP_MSG((" otp size = %d, boundary = 0x%x, nv base = 0x%x\n", lim, bound, base));
1848 if (tsz != 0) {
1849 OTP_MSG((" Found %d bytes in %d good chunks out of %d\n", tsz, gchunks, chunk));
1850 } else {
1851 OTP_MSG((" No good chunks found out of %d\n", chunk));
1854 *len = offset;
1856 out:
1857 if (rawotp)
1858 MFREE(si_osh(oi->sih), rawotp, lim);
1859 si_setcoreidx(oi->sih, idx);
1861 return rc;
1864 #ifdef BCMNVRAMW
1865 #if defined(BCMDBG) || defined(WLTEST)
1866 static uint st_n, st_s, st_hwm, pp_hwm;
1867 #ifdef OTP_FORCEFAIL
1868 static uint forcefail_bitcount = 0;
1869 #endif /* OTP_FORCEFAIL */
1870 #endif /* BCMDBG || WLTEST */
1872 static int
1873 hndotp_write_bit(void *oh, chipcregs_t *cc, int bn, bool bit, int no_retry)
1875 otpinfo_t *oi = (otpinfo_t *)oh;
1876 uint row, col, j, k;
1877 uint32 pwait, init_pwait, otpc, otpp, pst, st;
1878 osl_t *osh;
1880 osh = si_osh(oi->sih);
1881 ASSERT((bit >> 1) == 0);
1883 #ifdef OTP_FORCEFAIL
1884 OTP_MSG(("%s: [0x%x] = 0x%x\n", __FUNCTION__, wn * 2, data));
1885 #endif
1887 /* This is bit-at-a-time writing, future cores may do word-at-a-time */
1888 if (oi->ccrev == 12) {
1889 otpc = 0x20000001;
1890 init_pwait = 0x00000200;
1891 } else if (oi->ccrev == 22) {
1892 otpc = 0x20000001;
1893 init_pwait = 0x00000400;
1894 } else {
1895 otpc = 0x20000001;
1896 init_pwait = 0x00004000;
1899 pwait = init_pwait;
1900 row = bn / 65;
1901 col = bn % 65;
1902 otpp = OTPP_START_BUSY |
1903 ((bit << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) |
1904 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
1905 (col & OTPP_COL_MASK);
1906 j = 0;
1907 while (1) {
1908 j++;
1909 if (j > 1) {
1910 OTP_DBG(("row %d, col %d, val %d, otpc 0x%x, otpp 0x%x\n",
1911 row, col, bit, (otpc | pwait), otpp));
1913 W_REG(osh, &cc->otpcontrol, otpc | pwait);
1914 W_REG(osh, &cc->otpprog, otpp);
1915 pst = R_REG(osh, &cc->otpprog);
1916 for (k = 0; ((pst & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
1917 pst = R_REG(osh, &cc->otpprog);
1918 #if defined(BCMDBG) || defined(WLTEST)
1919 if (k > pp_hwm)
1920 pp_hwm = k;
1921 #endif /* BCMDBG || WLTEST */
1922 if (k >= OTPP_TRIES) {
1923 OTP_ERR(("BUSY stuck: pst=0x%x, count=%d\n", pst, k));
1924 st = OTPS_PROGFAIL;
1925 break;
1927 st = R_REG(osh, &cc->otpstatus);
1928 if (((st & OTPS_PROGFAIL) == 0) || (pwait == OTPC_PROGWAIT) || (no_retry)) {
1929 break;
1930 } else {
1931 if ((oi->ccrev == 12) || (oi->ccrev == 22))
1932 pwait = (pwait << 3) & OTPC_PROGWAIT;
1933 else
1934 pwait = (pwait << 1) & OTPC_PROGWAIT;
1935 if (pwait == 0)
1936 pwait = OTPC_PROGWAIT;
1939 #if defined(BCMDBG) || defined(WLTEST)
1940 st_n++;
1941 st_s += j;
1942 if (j > st_hwm)
1943 st_hwm = j;
1944 #ifdef OTP_FORCEFAIL
1945 if (forcefail_bitcount++ == OTP_FORCEFAIL * 16) {
1946 OTP_DBG(("Forcing PROGFAIL on bit %d (FORCEFAIL = %d/0x%x)\n",
1947 forcefail_bitcount, OTP_FORCEFAIL, OTP_FORCEFAIL));
1948 st = OTPS_PROGFAIL;
1950 #endif
1951 #endif /* BCMDBG || WLTEST */
1952 if (st & OTPS_PROGFAIL) {
1953 OTP_ERR(("After %d tries: otpc = 0x%x, otpp = 0x%x/0x%x, otps = 0x%x\n",
1954 j, otpc | pwait, otpp, pst, st));
1955 OTP_ERR(("otp prog failed. bit=%d, ppret=%d, ret=%d\n", bit, k, j));
1956 return 1;
1959 return 0;
1962 static int
1963 hndotp_write_word(void *oh, chipcregs_t *cc, int wn, uint16 data)
1965 uint base, i;
1966 int err = 0;
1968 OTP_MSG(("%s: wn %d data %x\n", __FUNCTION__, wn, data));
1970 /* There is one test bit for each row */
1971 base = (wn * 16) + (wn / 4);
1973 for (i = 0; i < 16; i++) {
1974 err += hndotp_write_bit(oh, cc, base + i, data & 1, 0);
1975 data >>= 1;
1976 /* abort write after first error to avoid stress the charge-pump */
1977 if (err) {
1978 OTP_DBG(("%s: wn %d fail on bit %d\n", __FUNCTION__, wn, i));
1979 break;
1983 return err;
1986 static int
1987 hndotp_valid_rce(void *oh, chipcregs_t *cc, int i)
1989 otpinfo_t *oi = (otpinfo_t *)oh;
1990 osl_t *osh;
1991 uint32 hwv, fw, rce, e, sign, row, st;
1993 ASSERT(oi->ccrev >= 18);
1995 /* HW valid bit */
1996 osh = si_osh(oi->sih);
1997 st = R_REG(osh, &cc->otpstatus);
1998 hwv = (st & OTPS_RCEV_MSK) & (1 << (OTPS_RCEV_SHIFT + i));
2000 if (i < 3) {
2001 e = i;
2002 fw = hndotp_size(oh)/2 + OTP_RC0_OFF + e;
2003 } else {
2004 e = i - 3;
2005 fw = hndotp_size(oh)/2 + OTP_RC1_OFF + e;
2008 rce = hndotp_otpr(oh, cc, fw+1) << 16 | hndotp_otpr(oh, cc, fw);
2009 rce >>= ((e * OTP_RCE_BITS) + OTP_RCE_BIT0 - (e * 16));
2010 row = rce & OTP_RCE_ROW_MASK;
2011 sign = (rce >> OTP_RCE_ROW_SZ) & OTP_RCE_SIGN_MASK;
2013 OTP_MSG(("rce %d sign %x row %d hwv %x\n", i, sign, row, hwv));
2015 return (sign == OTP_SIGNATURE) ? row : -1;
2018 static int
2019 hndotp_write_rce(void *oh, chipcregs_t *cc, int r, uint16* data)
2021 int i, rce = -1;
2022 uint32 sign;
2024 ASSERT(((otpinfo_t *)oh)->ccrev >= 18);
2025 ASSERT(r >= 0 && r < hndotp_size(oh)/(2*OTP_WPR));
2026 ASSERT(data);
2028 for (rce = OTP_RCE_ROW_SZ -1; rce >= 0; rce--) {
2029 int e, rt, rcr, bit, err = 0;
2031 int rr = hndotp_valid_rce(oh, cc, rce);
2032 /* redundancy row in use already */
2033 if (rr != -1) {
2034 if (rr == r) {
2035 OTP_MSG(("%s: row %d already replaced by RCE %d",
2036 __FUNCTION__, r, rce));
2037 return 0;
2040 continue; /* If row used, go for the next row */
2044 * previously used bad rce entry maybe treaed as valid rce and used again, abort on
2045 * first bit error to avoid stress the charge pump
2048 /* Write the data to the redundant row */
2049 for (i = 0; i < OTP_WPR; i++) {
2050 err += hndotp_write_word(oh, cc, hndotp_size(oh)/2+OTP_RD_OFF+rce*4+i,
2051 data[i]);
2052 if (err) {
2053 OTP_MSG(("fail to write redundant row %d\n", rce));
2054 break;
2058 /* Now write the redundant row index */
2059 if (rce < 3) {
2060 e = rce;
2061 rcr = hndotp_size(oh)/2 + OTP_RC0_OFF;
2062 } else {
2063 e = rce - 3;
2064 rcr = hndotp_size(oh)/2 + OTP_RC1_OFF;
2067 /* Write row numer bit-by-bit */
2068 bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0;
2069 rt = r;
2070 for (i = 0; i < OTP_RCE_ROW_SZ; i++) {
2071 /* If any timeout happened, invalidate the subsequent bits with 0 */
2072 if (hndotp_write_bit(oh, cc, bit, (rt & (err ? 0 : 1)), err)) {
2073 OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row"
2074 " number bit %x\n", __FUNCTION__, r, rce, i));
2075 err++;
2077 rt >>= 1;
2078 bit ++;
2081 /* Write the RCE signature bit-by-bit */
2082 sign = OTP_SIGNATURE;
2083 for (i = 0; i < OTP_RCE_SIGN_SZ; i++) {
2084 /* If any timeout happened, invalidate the subsequent bits with 0 */
2085 if (hndotp_write_bit(oh, cc, bit, (sign & (err ? 0 : 1)), err)) {
2086 OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row"
2087 " number bit %x\n", __FUNCTION__, r, rce, i));
2088 err++;
2090 sign >>= 1;
2091 bit ++;
2094 if (err) {
2095 OTP_ERR(("%s: row %d not fixed by RCE %d due to %d timeouts. try next"
2096 " RCE\n", __FUNCTION__, r, rce, err));
2097 continue;
2098 } else {
2099 OTP_MSG(("%s: Fixed row %d by RCE %d\n", __FUNCTION__, r, rce));
2100 return BCME_OK;
2104 OTP_ERR(("All RCE's are in use. Failed fixing OTP.\n"));
2105 /* Fatal error, unfixable. MFGC will have to fail. Board needs to be discarded!! */
2106 return BCME_NORESOURCE;
2109 /* Write a row and fix it with RCE if any error detected */
2110 static int
2111 hndotp_write_row(void *oh, chipcregs_t *cc, int wn, uint16* data, bool rewrite)
2113 otpinfo_t *oi = (otpinfo_t *)oh;
2114 int err = 0, i;
2116 ASSERT(wn % OTP_WPR == 0);
2118 /* Write the data */
2119 for (i = 0; i < OTP_WPR; i++) {
2120 if (rewrite && (data[i] == hndotp_otpr(oh, cc, wn+i)))
2121 continue;
2123 err += hndotp_write_word(oh, cc, wn + i, data[i]);
2126 /* Fix this row if any error */
2127 if (err && (oi->ccrev >= 18)) {
2128 OTP_DBG(("%s: %d write errors in row %d. Fixing...\n", __FUNCTION__, err, wn/4));
2129 if ((err = hndotp_write_rce(oh, cc, wn / OTP_WPR, data)))
2130 OTP_MSG(("%s: failed to fix row %d\n", __FUNCTION__, wn/4));
2133 return err;
2136 /* expects the caller to disable interrupts before calling this routine */
2137 static int
2138 hndotp_write_region(void *oh, int region, uint16 *data, uint wlen)
2140 otpinfo_t *oi = (otpinfo_t *)oh;
2141 uint32 st;
2142 uint wn, base = 0, lim;
2143 int ret = BCME_OK;
2144 uint idx;
2145 chipcregs_t *cc;
2146 bool rewrite = FALSE;
2147 uint32 save_clk;
2149 ASSERT(wlen % OTP_WPR == 0);
2151 idx = si_coreidx(oi->sih);
2152 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2153 ASSERT(cc != NULL);
2155 /* Check valid region */
2156 if ((region != OTP_HW_REGION) &&
2157 (region != OTP_SW_REGION) &&
2158 (region != OTP_CID_REGION)) {
2159 ret = BCME_BADARG;
2160 goto out;
2163 /* Region already written? */
2164 st = oi->hwprot | oi-> signvalid;
2165 if ((st & region) != 0)
2166 rewrite = TRUE;
2168 /* HW and CID have to be written before SW */
2169 if ((((st & (OTP_HW_REGION | OTP_CID_REGION)) == 0) &&
2170 (st & OTP_SW_REGION) != 0)) {
2171 OTP_ERR(("%s: HW/CID region should be programmed first\n", __FUNCTION__));
2172 ret = BCME_BADARG;
2173 goto out;
2176 /* Bounds for the region */
2177 lim = (oi->size / 2) + OTP_SWLIM_OFF;
2178 if (region == OTP_HW_REGION) {
2179 base = 0;
2180 } else if (region == OTP_SW_REGION) {
2181 base = oi->boundary / 2;
2182 } else if (region == OTP_CID_REGION) {
2183 base = (oi->size / 2) + OTP_CID_OFF;
2184 lim = (oi->size / 2) + OTP_LIM_OFF;
2187 if (wlen > (lim - base)) {
2188 ret = BCME_BUFTOOLONG;
2189 goto out;
2191 lim = base + wlen;
2193 #if defined(BCMDBG) || defined(WLTEST)
2194 st_n = st_s = st_hwm = pp_hwm = 0;
2195 #endif /* BCMDBG || WLTEST */
2197 /* force ALP for progrramming stability */
2198 save_clk = R_REG(oi->osh, &cc->clk_ctl_st);
2199 OR_REG(oi->osh, &cc->clk_ctl_st, CCS_FORCEALP);
2200 OSL_DELAY(10);
2202 /* Write the data row by row */
2203 for (wn = base; wn < lim; wn += OTP_WPR, data += OTP_WPR) {
2204 if ((ret = hndotp_write_row(oh, cc, wn, data, rewrite)) != 0) {
2205 if (ret == BCME_NORESOURCE) {
2206 OTP_ERR(("%s: Abort at word %x\n", __FUNCTION__, wn));
2207 break;
2212 /* Don't need to update signature & boundary if rewrite */
2213 if (rewrite)
2214 goto out_rclk;
2216 /* Done with the data, write the signature & boundary if needed */
2217 if (region == OTP_HW_REGION) {
2218 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF, lim * 2) != 0) {
2219 ret = BCME_NORESOURCE;
2220 goto out_rclk;
2222 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF,
2223 OTP_SIGNATURE) != 0) {
2224 ret = BCME_NORESOURCE;
2225 goto out_rclk;
2227 oi->boundary = lim * 2;
2228 oi->signvalid |= OTP_HW_REGION;
2229 } else if (region == OTP_SW_REGION) {
2230 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_SWSIGN_OFF,
2231 OTP_SIGNATURE) != 0) {
2232 ret = BCME_NORESOURCE;
2233 goto out_rclk;
2235 oi->signvalid |= OTP_SW_REGION;
2236 } else if (region == OTP_CID_REGION) {
2237 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_CIDSIGN_OFF,
2238 OTP_SIGNATURE) != 0) {
2239 ret = BCME_NORESOURCE;
2240 goto out_rclk;
2242 oi->signvalid |= OTP_CID_REGION;
2245 out_rclk:
2246 /* Restore clock */
2247 W_REG(oi->osh, &cc->clk_ctl_st, save_clk);
2249 out:
2250 #if defined(BCMDBG) || defined(WLTEST)
2251 OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n",
2252 st_n, st_s, st_n, st_n?(st_s / st_n):0, st_hwm, pp_hwm));
2253 #endif
2255 si_setcoreidx(oi->sih, idx);
2257 return ret;
2260 /* For HND OTP, there's no space for appending after filling in SROM image */
2261 static int
2262 hndotp_cis_append_region(si_t *sih, int region, char *vars, int count)
2264 return otp_write_region(sih, region, (uint16*)vars, count/2);
2268 * Fill all unwritten RCE signature with 0 and return the number of them.
2269 * HNDOTP needs lock due to the randomness of unprogrammed content.
2271 static int
2272 hndotp_lock(void *oh)
2274 otpinfo_t *oi = (otpinfo_t *)oh;
2275 int i, j, e, rcr, bit, ret = 0;
2276 uint32 st, idx;
2277 chipcregs_t *cc;
2279 ASSERT(oi->ccrev >= 18);
2281 idx = si_coreidx(oi->sih);
2282 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2283 ASSERT(cc != NULL);
2285 /* Region already written? */
2286 st = oi->hwprot | oi-> signvalid;
2287 if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == 0) {
2288 si_setcoreidx(oi->sih, idx);
2289 return BCME_NOTREADY; /* Don't lock unprogrammed OTP */
2292 /* Find the highest valid RCE */
2293 for (i = 0; i < OTP_RCE_ROW_SZ -1; i++) {
2294 if ((hndotp_valid_rce(oh, cc, i) != -1))
2295 break;
2297 i--; /* Start invalidating from the next RCE */
2299 for (; i >= 0; i--) {
2300 if ((hndotp_valid_rce(oh, cc, i) == -1)) {
2302 ret++; /* This is a unprogrammed row */
2304 /* Invalidate the row with 0 */
2305 if (i < 3) {
2306 e = i;
2307 rcr = hndotp_size(oh)/2 + OTP_RC0_OFF;
2308 } else {
2309 e = i - 3;
2310 rcr = hndotp_size(oh)/2 + OTP_RC1_OFF;
2313 /* Fill row numer and signature with 0 bit-by-bit */
2314 bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0;
2315 for (j = 0; j < (OTP_RCE_ROW_SZ + OTP_RCE_SIGN_SZ); j++) {
2316 hndotp_write_bit(oh, cc, bit, 0, 1);
2317 bit ++;
2320 OTP_MSG(("locking rce %d\n", i));
2324 si_setcoreidx(oi->sih, idx);
2326 return ret;
2329 /* expects the caller to disable interrupts before calling this routine */
2330 static int
2331 hndotp_nvwrite(void *oh, uint16 *data, uint wlen)
2333 otpinfo_t *oi = (otpinfo_t *)oh;
2334 uint32 st;
2335 uint16 crc, clen, *p, hdr[2];
2336 uint wn, base = 0, lim;
2337 int err, gerr = 0;
2338 uint idx;
2339 chipcregs_t *cc;
2341 /* otp already written? */
2342 st = oi->hwprot | oi-> signvalid;
2343 if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == (OTP_HW_REGION | OTP_SW_REGION))
2344 return BCME_EPERM;
2346 /* save the orig core */
2347 idx = si_coreidx(oi->sih);
2348 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2349 ASSERT(cc != NULL);
2351 /* Bounds for the region */
2352 lim = (oi->size / 2) + OTP_SWLIM_OFF;
2353 base = 0;
2355 /* Look for possible chunks from the end down */
2356 wn = lim;
2357 while (wn > 0) {
2358 wn--;
2359 if (hndotp_otpr(oh, cc, wn) == OTP_MAGIC) {
2360 base = wn + (hndotp_otpr(oh, cc, wn + 1) / 2);
2361 break;
2364 if (base == 0) {
2365 OTP_MSG(("Unprogrammed otp\n"));
2366 } else {
2367 OTP_MSG(("Found some chunks, skipping to 0x%x\n", base * 2));
2369 if ((wlen + 3) > (lim - base)) {
2370 err = BCME_NORESOURCE;
2371 goto out;
2374 #if defined(BCMDBG) || defined(WLTEST)
2375 st_n = st_s = st_hwm = pp_hwm = 0;
2376 #endif /* BCMDBG || WLTEST */
2378 /* Prepare the header and crc */
2379 hdr[0] = OTP_MAGIC;
2380 hdr[1] = (wlen + 3) * 2;
2381 crc = hndcrc16((uint8 *)hdr, sizeof(hdr), CRC16_INIT_VALUE);
2382 crc = hndcrc16((uint8 *)data, wlen * 2, crc);
2383 crc = ~crc;
2385 do {
2386 p = data;
2387 wn = base + 2;
2388 lim = base + wlen + 2;
2390 OTP_MSG(("writing chunk, 0x%x bytes @ 0x%x-0x%x\n", wlen * 2,
2391 base * 2, (lim + 1) * 2));
2393 /* Write the header */
2394 err = hndotp_write_word(oh, cc, base, hdr[0]);
2396 /* Write the data */
2397 while (wn < lim) {
2398 err += hndotp_write_word(oh, cc, wn++, *p++);
2400 /* If there has been an error, close this chunk */
2401 if (err != 0) {
2402 OTP_MSG(("closing early @ 0x%x\n", wn * 2));
2403 break;
2407 /* If we wrote the whole chunk, write the crc */
2408 if (wn == lim) {
2409 OTP_MSG((" whole chunk written, crc = 0x%x\n", crc));
2410 err += hndotp_write_word(oh, cc, wn++, crc);
2411 clen = hdr[1];
2412 } else {
2413 /* If there was an error adjust the count to point to
2414 * the word after the error so we can start the next
2415 * chunk there.
2417 clen = (wn - base) * 2;
2418 OTP_MSG((" partial chunk written, chunk len = 0x%x\n", clen));
2420 /* And now write the chunk length */
2421 err += hndotp_write_word(oh, cc, base + 1, clen);
2423 if (base == 0) {
2424 /* Write the signature and boundary if this is the HW region,
2425 * but don't report failure if either of these 2 writes fail.
2427 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF,
2428 wn * 2) == 0)
2429 gerr += hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF,
2430 OTP_SIGNATURE);
2431 else
2432 gerr++;
2433 oi->boundary = wn * 2;
2434 oi->signvalid |= OTP_HW_REGION;
2437 if (err != 0) {
2438 gerr += err;
2439 /* Errors, do it all over again if there is space left */
2440 if ((wlen + 3) <= ((oi->size / 2) + OTP_SWLIM_OFF - wn)) {
2441 base = wn;
2442 lim = base + wlen + 2;
2443 OTP_ERR(("Programming errors, retry @ 0x%x\n", wn * 2));
2444 } else {
2445 OTP_ERR(("Programming errors, no space left ( 0x%x)\n", wn * 2));
2446 break;
2449 } while (err != 0);
2451 OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n",
2452 st_n, st_s, st_n, st_s / st_n, st_hwm, pp_hwm));
2454 if (gerr != 0)
2455 OTP_MSG(("programming %s after %d errors\n", (err == 0) ? "succedded" : "failed",
2456 gerr));
2457 out:
2458 /* done */
2459 si_setcoreidx(oi->sih, idx);
2461 if (err)
2462 return BCME_ERROR;
2463 else
2464 return 0;
2466 #endif /* BCMNVRAMW */
2468 #if defined(WLTEST)
2469 static uint16
2470 hndotp_otprb16(void *oh, chipcregs_t *cc, uint wn)
2472 uint base, i;
2473 uint16 val, bit;
2475 base = (wn * 16) + (wn / 4);
2476 val = 0;
2477 for (i = 0; i < 16; i++) {
2478 if ((bit = hndotp_read_bit(oh, cc, base + i)) == 0xffff)
2479 break;
2480 val = val | (bit << i);
2482 if (i < 16)
2483 val = 0xaaaa;
2484 return val;
2487 static int
2488 hndotp_dump(void *oh, int arg, char *buf, uint size)
2490 otpinfo_t *oi = (otpinfo_t *)oh;
2491 chipcregs_t *cc;
2492 uint idx, i, count, lil;
2493 uint16 val;
2494 struct bcmstrbuf b;
2496 idx = si_coreidx(oi->sih);
2497 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2498 ASSERT(cc != NULL);
2500 if (arg >= 16)
2501 arg -= 16;
2503 if (arg == 2) {
2504 count = 66 * 4;
2505 lil = 3;
2506 } else {
2507 count = (oi->size / 2) + OTP_RC_LIM_OFF;
2508 lil = 7;
2511 OTP_MSG(("%s: arg %d, size %d, words %d\n", __FUNCTION__, arg, size, count));
2512 bcm_binit(&b, buf, size);
2513 for (i = 0; i < count; i++) {
2514 if ((i & lil) == 0)
2515 bcm_bprintf(&b, "0x%04x:", 2 * i);
2517 if (arg == 0)
2518 val = hndotp_otpr(oh, cc, i);
2519 else
2520 val = hndotp_otprb16(oi, cc, i);
2521 bcm_bprintf(&b, " 0x%04x", val);
2522 if ((i & lil) == lil) {
2523 if (arg == 2) {
2524 bcm_bprintf(&b, " %d\n",
2525 hndotp_read_bit(oh, cc, ((i / 4) * 65) + 64) & 1);
2526 } else {
2527 bcm_bprintf(&b, "\n");
2531 if ((i & lil) != lil)
2532 bcm_bprintf(&b, "\n");
2534 OTP_MSG(("%s: returning %d, left %d, wn %d\n",
2535 __FUNCTION__, (int)(b.buf - b.origbuf), b.size, i));
2537 si_setcoreidx(oi->sih, idx);
2539 return ((int)(b.buf - b.origbuf));
2541 #endif
2543 static otp_fn_t hndotp_fn = {
2544 (otp_size_t)hndotp_size,
2545 (otp_read_bit_t)hndotp_read_bit,
2547 (otp_init_t)hndotp_init,
2548 (otp_read_region_t)hndotp_read_region,
2549 (otp_nvread_t)hndotp_nvread,
2550 #ifdef BCMNVRAMW
2551 (otp_write_region_t)hndotp_write_region,
2552 (otp_cis_append_region_t)hndotp_cis_append_region,
2553 (otp_lock_t)hndotp_lock,
2554 (otp_nvwrite_t)hndotp_nvwrite,
2555 #endif /* BCMNVRAMW */
2557 #if defined(WLTEST)
2558 (otp_dump_t)hndotp_dump,
2559 #endif
2561 (otp_status_t)hndotp_status,
2562 #ifdef BCMNVRAMW
2563 (otp_write_word_t)NULL,
2564 #endif /* BCMNVRAMW */
2565 (otp_read_word_t)hndotp_read_word,
2568 #endif /* BCMHNDOTP */
2571 * Common Code: Compiled for IPX / HND / AUTO
2572 * otp_status()
2573 * otp_size()
2574 * otp_read_bit()
2575 * otp_init()
2576 * otp_read_region()
2577 * otp_read_word()
2578 * otp_nvread()
2579 * otp_write_region()
2580 * otp_write_word()
2581 * otp_cis_append_region()
2582 * otp_lock()
2583 * otp_nvwrite()
2584 * otp_dump()
2588 otp_status(void *oh)
2590 otpinfo_t *oi = (otpinfo_t *)oh;
2592 return oi->fn->status(oh);
2596 otp_size(void *oh)
2598 otpinfo_t *oi = (otpinfo_t *)oh;
2600 return oi->fn->size(oh);
2603 uint16
2604 otp_read_bit(void *oh, uint offset)
2606 otpinfo_t *oi = (otpinfo_t *)oh;
2607 uint idx = si_coreidx(oi->sih);
2608 chipcregs_t *cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2609 uint16 readBit = (uint16)oi->fn->read_bit(oh, cc, offset);
2610 si_setcoreidx(oi->sih, idx);
2611 return readBit;
2614 void *
2615 BCMNMIATTACHFN(otp_init)(si_t *sih)
2617 otpinfo_t *oi;
2618 void *ret = NULL;
2620 oi = &otpinfo;
2621 bzero(oi, sizeof(otpinfo_t));
2623 oi->ccrev = sih->ccrev;
2625 #ifdef BCMIPXOTP
2626 if (OTPTYPE_IPX(oi->ccrev))
2627 oi->fn = &ipxotp_fn;
2628 #endif
2630 #ifdef BCMHNDOTP
2631 if (OTPTYPE_HND(oi->ccrev))
2632 oi->fn = &hndotp_fn;
2633 #endif
2635 if (oi->fn == NULL) {
2636 OTP_ERR(("otp_init: unsupported OTP type\n"));
2637 return NULL;
2640 oi->sih = sih;
2641 oi->osh = si_osh(oi->sih);
2643 ret = (oi->fn->init)(sih);
2645 return ret;
2649 BCMNMIATTACHFN(otp_read_region)(si_t *sih, int region, uint16 *data, uint *wlen)
2651 bool wasup = FALSE;
2652 void *oh;
2653 int err = 0;
2655 if (!(wasup = si_is_otp_powered(sih)))
2656 si_otp_power(sih, TRUE);
2658 if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2659 err = BCME_NOTREADY;
2660 goto out;
2663 oh = otp_init(sih);
2664 if (oh == NULL) {
2665 OTP_ERR(("otp_init failed.\n"));
2666 err = BCME_ERROR;
2667 goto out;
2670 err = (((otpinfo_t*)oh)->fn->read_region)(oh, region, data, wlen);
2672 out:
2673 if (!wasup)
2674 si_otp_power(sih, FALSE);
2676 return err;
2680 otp_read_word(si_t *sih, uint wn, uint16 *data)
2682 bool wasup = FALSE;
2683 void *oh;
2684 int err = 0;
2686 if (!(wasup = si_is_otp_powered(sih)))
2687 si_otp_power(sih, TRUE);
2689 if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2690 err = BCME_NOTREADY;
2691 goto out;
2694 oh = otp_init(sih);
2695 if (oh == NULL) {
2696 OTP_ERR(("otp_init failed.\n"));
2697 err = BCME_ERROR;
2698 goto out;
2701 if (((otpinfo_t*)oh)->fn->read_word == NULL) {
2702 err = BCME_UNSUPPORTED;
2703 goto out;
2705 err = (((otpinfo_t*)oh)->fn->read_word)(oh, wn, data);
2707 out:
2708 if (!wasup)
2709 si_otp_power(sih, FALSE);
2711 return err;
2715 otp_nvread(void *oh, char *data, uint *len)
2717 otpinfo_t *oi = (otpinfo_t *)oh;
2719 return oi->fn->nvread(oh, data, len);
2722 #ifdef BCMNVRAMW
2724 BCMNMIATTACHFN(otp_write_region)(si_t *sih, int region, uint16 *data, uint wlen)
2726 bool wasup = FALSE;
2727 void *oh;
2728 int err = 0;
2730 if (!(wasup = si_is_otp_powered(sih)))
2731 si_otp_power(sih, TRUE);
2733 if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2734 err = BCME_NOTREADY;
2735 goto out;
2738 oh = otp_init(sih);
2739 if (oh == NULL) {
2740 OTP_ERR(("otp_init failed.\n"));
2741 err = BCME_ERROR;
2742 goto out;
2745 err = (((otpinfo_t*)oh)->fn->write_region)(oh, region, data, wlen);
2747 out:
2748 if (!wasup)
2749 si_otp_power(sih, FALSE);
2751 return err;
2755 otp_write_word(si_t *sih, uint wn, uint16 data)
2757 bool wasup = FALSE;
2758 void *oh;
2759 int err = 0;
2761 if (!(wasup = si_is_otp_powered(sih)))
2762 si_otp_power(sih, TRUE);
2764 if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2765 err = BCME_NOTREADY;
2766 goto out;
2769 oh = otp_init(sih);
2770 if (oh == NULL) {
2771 OTP_ERR(("otp_init failed.\n"));
2772 err = BCME_ERROR;
2773 goto out;
2776 if (((otpinfo_t*)oh)->fn->write_word == NULL) {
2777 err = BCME_UNSUPPORTED;
2778 goto out;
2780 err = (((otpinfo_t*)oh)->fn->write_word)(oh, wn, data);
2782 out:
2783 if (!wasup)
2784 si_otp_power(sih, FALSE);
2786 return err;
2790 otp_cis_append_region(si_t *sih, int region, char *vars, int count)
2792 void *oh = otp_init(sih);
2794 if (oh == NULL) {
2795 OTP_ERR(("otp_init failed.\n"));
2796 return -1;
2798 return (((otpinfo_t*)oh)->fn->cis_append_region)(sih, region, vars, count);
2802 otp_lock(si_t *sih)
2804 bool wasup = FALSE;
2805 void *oh;
2806 int ret = 0;
2808 if (!(wasup = si_is_otp_powered(sih)))
2809 si_otp_power(sih, TRUE);
2811 if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2812 ret = BCME_NOTREADY;
2813 goto out;
2816 oh = otp_init(sih);
2817 if (oh == NULL) {
2818 OTP_ERR(("otp_init failed.\n"));
2819 ret = BCME_ERROR;
2820 goto out;
2823 ret = (((otpinfo_t*)oh)->fn->lock)(oh);
2825 out:
2826 if (!wasup)
2827 si_otp_power(sih, FALSE);
2829 return ret;
2833 otp_nvwrite(void *oh, uint16 *data, uint wlen)
2835 otpinfo_t *oi = (otpinfo_t *)oh;
2837 return oi->fn->nvwrite(oh, data, wlen);
2839 #endif /* BCMNVRAMW */
2841 #if defined(WLTEST)
2843 otp_dump(void *oh, int arg, char *buf, uint size)
2845 otpinfo_t *oi = (otpinfo_t *)oh;
2847 return oi->fn->dump(oh, arg, buf, size);
2851 otp_dumpstats(void *oh, int arg, char *buf, uint size)
2853 otpinfo_t *oi = (otpinfo_t *)oh;
2854 struct bcmstrbuf b;
2856 bcm_binit(&b, buf, size);
2858 bcm_bprintf(&b, "\nOTP, ccrev 0x%04x\n", oi->ccrev);
2859 #if defined(BCMIPXOTP)
2860 bcm_bprintf(&b, "wsize %d rows %d cols %d\n", oi->wsize, oi->rows, oi->cols);
2861 bcm_bprintf(&b, "hwbase %d hwlim %d swbase %d swlim %d fusebits %d\n",
2862 oi->hwbase, oi->hwlim, oi->swbase, oi->swlim, oi->fbase, oi->flim, oi->fusebits);
2863 bcm_bprintf(&b, "otpgu_base %d status %d\n", oi->otpgu_base, oi->status);
2864 #endif
2865 #if defined(BCMHNDOTP)
2866 bcm_bprintf(&b, "OLD OTP, size %d hwprot 0x%x signvalid 0x%x boundary %d\n",
2867 oi->size, oi->hwprot, oi->signvalid, oi->boundary);
2868 #endif
2869 bcm_bprintf(&b, "\n");
2871 return 200; /* real buf length, pick one to cover above print */
2874 #endif