Broadcom SDK and wireless driver: another attempt to update to ver. 5.10.147.0
[tomato.git] / release / src-rt / shared / bcmotp.c
blobe82bbe1d5db889e0cfd3bed2244e43481de62c0c
1 /*
2 * OTP support.
4 * Copyright (C) 2009, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
12 * $Id: bcmotp.c,v 1.54.2.58 2010/01/28 03:48:24 Exp $
15 #include <typedefs.h>
16 #include <bcmdefs.h>
17 #include <osl.h>
18 #include <bcmdevs.h>
19 #include <bcmutils.h>
20 #include <siutils.h>
21 #include <bcmendian.h>
22 #include <hndsoc.h>
23 #include <sbchipc.h>
24 #include <bcmotp.h>
27 #define OTP_ERR_VAL 0x0001
28 #define OTP_MSG_VAL 0x0002
29 #define OTP_DBG_VAL 0x0004
31 uint32 otp_msg_level = OTP_ERR_VAL;
33 #define OTP_ERR(args)
34 #define OTP_MSG(args)
35 #define OTP_DBG(args)
38 * Common Code: Compiled for IPX / HND / AUTO
40 #define HWSW_RGN(rgn) (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
42 #define OTPP_TRIES 10000000 /* # of tries for OTPP */
44 /* Maximum OTP redundancy entries. */
45 #define MAXNUMRDES 9
47 /* OTP common function type */
48 typedef int (*otp_status_t)(void *oh);
49 typedef int (*otp_size_t)(void *oh);
50 typedef void* (*otp_init_t)(si_t *sih);
51 typedef uint16 (*otp_read_bit_t)(void *oh, chipcregs_t *cc, uint off);
52 typedef int (*otp_read_region_t)(si_t *sih, int region, uint16 *data, uint *wlen);
53 typedef int (*otp_nvread_t)(void *oh, char *data, uint *len);
54 typedef int (*otp_write_region_t)(void *oh, int region, uint16 *data, uint wlen);
55 typedef int (*otp_cis_append_region_t)(si_t *sih, int region, char *vars, int count);
56 typedef int (*otp_lock_t)(si_t *sih);
57 typedef int (*otp_nvwrite_t)(void *oh, uint16 *data, uint wlen);
58 typedef int (*otp_dump_t)(void *oh, int arg, char *buf, uint size);
60 /* OTP function struct */
61 typedef struct otp_fn_s {
62 otp_status_t status;
63 otp_size_t size;
64 otp_read_bit_t read_bit;
65 otp_init_t init;
66 otp_read_region_t read_region;
67 otp_nvread_t nvread;
68 #ifdef BCMNVRAMW
69 otp_write_region_t write_region;
70 otp_cis_append_region_t cis_append_region;
71 otp_lock_t lock;
72 otp_nvwrite_t nvwrite;
73 #endif /* BCMNVRAMW */
74 #if defined(WLTEST)
75 otp_dump_t dump;
76 #endif
77 uint32 magic;
78 } otp_fn_t;
79 #define OTP_FN_MAGIC 0x87654321
81 typedef struct {
82 uint ccrev; /* chipc revision */
83 otp_fn_t *fn; /* OTP functions */
84 si_t *sih; /* Saved sb handle */
85 osl_t *osh;
86 #if defined(BCMAUTOOTP) || !defined(BCMHNDOTP) /* Newer IPX OTP wrapper */
87 /* Geometry */
88 uint16 wsize; /* Size of otp in words */
89 uint16 rows;
90 uint16 cols;
91 /* Flag bits (lock/prog/rv). Reflected only when OTP is power cycled */
92 uint32 status;
93 /* Subregion boundaries */
94 uint16 hwbase; /* hardware subregion offset */
95 uint16 hwlim; /* hardware subregion boundary */
96 uint16 swbase; /* software subregion offset */
97 uint16 swlim; /* software subregion boundary */
98 uint16 fbase; /* fuse subregion offset */
99 uint16 flim; /* fuse subregion boundary */
100 /* Use these to hide differences between different revs */
101 int otpgu_base; /* offset to General Use Region */
102 #ifdef BCMNVRAMW
103 struct {
104 uint8 width; /* entry width in bits */
105 uint8 val_shift; /* value bit offset in the entry */
106 uint8 offsets; /* # entries */
107 uint8 stat_shift; /* valid bit in otpstatus */
108 uint16 offset[MAXNUMRDES]; /* entry offset in OTP */
109 } rde_cb; /* OTP redundancy control blocks */
110 #endif /* BCMNVRAMW */
111 #endif /* BCMAUTOOTP || !BCMHNDOTP */
112 #if defined(BCMAUTOOTP) || defined(BCMHNDOTP) /* Older HND OTP wrapper */
113 uint size; /* Size of otp in bytes */
114 uint hwprot; /* Hardware protection bits */
115 uint signvalid; /* Signature valid bits */
116 int boundary; /* hw/sw boundary */
117 #endif /* BCMAUTOOTP || BCMHNDOTP */
118 } otpinfo_t;
120 static otpinfo_t otpinfo;
124 * IPX OTP Code: Compiled for IPX OTP or AUTO mode
125 * Exported functions:
126 * ipxotp_status()
127 * ipxotp_size()
128 * ipxotp_init()
129 * ipxotp_read_bit()
130 * ipxotp_read_region()
131 * ipxotp_nvread()
132 * ipxotp_write_region()
133 * ipxotp_cis_append_region()
134 * ipxotp_lock()
135 * ipxotp_nvwrite()
136 * ipxotp_dump()
138 * IPX internal functions:
139 * ipxotp_otpr()
140 * _ipxotp_init()
141 * ipxotp_write_bit()
142 * ipxotp_otpwb16()
143 * ipxotp_write_rde()
144 * ipxotp_fix_word16()
145 * ipxotp_check_word16()
146 * ipxotp_max_rgnsz()
147 * ipxotp_otprb16()
151 #if defined(BCMAUTOOTP) || !defined(BCMHNDOTP) /* Newer IPX OTP wrapper */
153 /* OTP layout */
154 /* CC revs 21, 24 and 27 OTP General Use Region word offset */
155 #define REVA4_OTPGU_BASE 12
157 /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
158 #define REVB8_OTPGU_BASE 20
160 /* Subregion word offsets in General Use region */
161 #define OTPGU_HSB_OFF 0
162 #define OTPGU_SFB_OFF 1
163 #define OTPGU_CI_OFF 2
164 #define OTPGU_P_OFF 3
165 #define OTPGU_SROM_OFF 4
167 /* Flag bit offsets in General Use region */
168 #define OTPGU_HWP_OFF 60
169 #define OTPGU_SWP_OFF 61
170 #define OTPGU_CIP_OFF 62
171 #define OTPGU_FUSEP_OFF 63
172 #define OTPGU_CIP_MSK 0x4000
173 #define OTPGU_P_MSK 0xf000
174 #define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16)
176 /* OTP Size */
177 #define OTP_SZ_FU_288 (288/8) /* 288 bits */
178 #define OTP_SZ_FU_72 (72/8) /* 72 bits */
179 #define OTP_SZ_CHECKSUM (16/8) /* 16 bits */
180 #define OTP4315_SWREG_SZ 178 /* 178 bytes */
182 static int
183 ipxotp_status(void *oh)
185 otpinfo_t *oi = (otpinfo_t *)oh;
186 return (int)(oi->status);
189 /* Return size in bytes */
190 static int
191 ipxotp_size(void *oh)
193 otpinfo_t *oi = (otpinfo_t *)oh;
194 return (int)oi->wsize * 2;
197 static uint16
198 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
200 otpinfo_t *oi;
202 oi = (otpinfo_t *)oh;
204 ASSERT(wn < oi->wsize);
205 ASSERT(cc != NULL);
207 return R_REG(oi->osh, &cc->sromotp[wn]);
210 static uint16
211 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
213 otpinfo_t *oi = (otpinfo_t *)oh;
214 uint k, row, col;
215 uint32 otpp, st;
217 row = off / oi->cols;
218 col = off % oi->cols;
220 otpp = OTPP_START_BUSY |
221 ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
222 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
223 ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
224 OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x",
225 __FUNCTION__, off, row, col, otpp));
226 W_REG(oi->osh, &cc->otpprog, otpp);
228 for (k = 0;
229 ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
230 k ++)
232 if (k >= OTPP_TRIES) {
233 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
234 return -1;
236 if (st & OTPP_READERR) {
237 OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, off));
238 return -1;
240 st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
242 OTP_DBG((" => %d\n", st));
243 return (int)st;
247 /* Calculate max HW/SW region byte size by substracting fuse region and checksum size,
248 * osizew is oi->wsize (OTP size - GU size) in words
250 static int
251 ipxotp_max_rgnsz(si_t *sih, int osizew)
253 int ret = 0;
255 switch (CHIPID(sih->chip)) {
256 case BCM4322_CHIP_ID:
257 case BCM43221_CHIP_ID:
258 case BCM43231_CHIP_ID:
259 ret = osizew*2 - OTP_SZ_FU_288 - OTP_SZ_CHECKSUM;
260 break;
261 case BCM43222_CHIP_ID:
262 case BCM43111_CHIP_ID:
263 case BCM43112_CHIP_ID:
265 case BCM43224_CHIP_ID:
266 case BCM43225_CHIP_ID:
267 case BCM43421_CHIP_ID:
268 case BCM4313_CHIP_ID:
269 ret = osizew*2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
270 break;
271 case BCM4319_CHIP_ID:
272 ret = osizew*2;
273 break;
274 default:
275 ASSERT(0); /* Don't konw about this chip */
278 OTP_MSG(("max region size %d bytes\n", ret));
279 return ret;
282 static void
283 BCMNMIATTACHFN(_ipxotp_init)(otpinfo_t *oi, chipcregs_t *cc)
285 uint k;
286 uint32 otpp, st;
288 /* record word offset of General Use Region for various chipcommon revs */
289 if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 || oi->sih->ccrev == 27) {
290 oi->otpgu_base = REVA4_OTPGU_BASE;
291 } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
292 oi->otpgu_base = REVB8_OTPGU_BASE;
293 } else {
294 OTP_ERR(("%s: chipc rev %d not supported\n", __FUNCTION__, oi->sih->ccrev));
297 /* First issue an init command so the status is up to date */
298 otpp = OTPP_START_BUSY |
299 ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
300 OTP_DBG(("%s: otpp = 0x%x", __FUNCTION__, otpp));
301 W_REG(oi->osh, &cc->otpprog, otpp);
302 for (k = 0;
303 ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
304 k ++)
306 if (k >= OTPP_TRIES) {
307 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
308 return;
311 /* Read OTP lock bits and subregion programmed indication bits */
312 oi->status = R_REG(oi->osh, &cc->otpstatus);
314 if ((CHIPID(oi->sih->chip) == BCM43222_CHIP_ID) ||
315 (CHIPID(oi->sih->chip) == BCM43111_CHIP_ID) ||
316 (CHIPID(oi->sih->chip) == BCM43112_CHIP_ID) ||
317 (CHIPID(oi->sih->chip) == BCM43224_CHIP_ID) ||
318 (CHIPID(oi->sih->chip) == BCM43225_CHIP_ID) ||
319 (CHIPID(oi->sih->chip) == BCM43421_CHIP_ID) ||
320 0) {
321 uint32 p_bits;
322 p_bits = (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & OTPGU_P_MSK)
323 >> OTPGU_P_SHIFT;
324 oi->status |= (p_bits << OTPS_GUP_SHIFT);
326 OTP_DBG(("%s: status 0x%x\n", __FUNCTION__, oi->status));
329 * h/w region base and fuse region limit are fixed to the top and
330 * the bottom of the general use region. Everything else can be flexible.
332 oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
333 oi->hwlim = oi->wsize;
334 if (oi->status & OTPS_GUP_HW) {
335 oi->hwlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
336 oi->swbase = oi->hwlim;
338 else
339 oi->swbase = oi->hwbase;
341 /* subtract fuse and checksum from beginning */
342 oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
343 if (oi->status & OTPS_GUP_SW) {
344 oi->swlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
345 oi->fbase = oi->swlim;
347 else
348 oi->fbase = oi->swbase;
350 oi->flim = oi->wsize;
352 OTP_DBG(("%s: hwbase %d/%d hwlim %d/%d\n", __FUNCTION__, oi->hwbase, oi->hwbase * 16,
353 oi->hwlim, oi->hwlim * 16));
354 OTP_DBG(("%s: swbase %d/%d swlim %d/%d\n", __FUNCTION__, oi->swbase, oi->swbase * 16,
355 oi->swlim, oi->swlim * 16));
356 OTP_DBG(("%s: fbase %d/%d flim %d/%d\n", __FUNCTION__, oi->fbase, oi->fbase * 16,
357 oi->flim, oi->flim * 16));
360 static void*
361 BCMNMIATTACHFN(ipxotp_init)(si_t *sih)
363 uint idx;
364 chipcregs_t *cc;
365 otpinfo_t *oi;
367 OTP_MSG(("%s: Use IPX OTP controller\n", __FUNCTION__));
369 /* Make sure we running IPX OTP */
370 ASSERT((sih->ccrev >= 21) && (sih->ccrev != 22));
371 if (sih->ccrev < 21 || sih->ccrev == 22)
372 return NULL;
374 /* Make sure OTP is not disabled */
375 if (si_is_otp_disabled(sih)) {
376 OTP_MSG(("%s: OTP is disabled\n", __FUNCTION__));
377 #if !defined(WLTEST)
378 return NULL;
379 #endif
382 /* Make sure OTP is powered up */
383 if (!si_is_otp_powered(sih)) {
384 OTP_ERR(("%s: OTP is powered down\n", __FUNCTION__));
385 return NULL;
388 oi = &otpinfo;
390 /* Check for otp size */
391 switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
392 case 0:
393 /* Nothing there */
394 OTP_ERR(("%s: no OTP\n", __FUNCTION__));
395 return NULL;
396 case 1: /* 32x64 */
397 oi->rows = 32;
398 oi->cols = 64;
399 oi->wsize = 128;
400 break;
401 case 2: /* 64x64 */
402 oi->rows = 64;
403 oi->cols = 64;
404 oi->wsize = 256;
405 break;
406 case 5: /* 96x64 */
407 oi->rows = 96;
408 oi->cols = 64;
409 oi->wsize = 384;
410 break;
411 default:
412 /* Don't know the geometry */
413 OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__));
414 return NULL;
417 OTP_MSG(("%s: rows %u cols %u wsize %u\n", __FUNCTION__, oi->rows, oi->cols, oi->wsize));
419 #ifdef BCMNVRAMW
420 /* Initialize OTP redundancy control blocks */
421 if (sih->ccrev == 21 || sih->ccrev == 24) {
422 uint16 offset[] = {64, 79, 94, 109, 128, 143, 158, 173};
423 bcopy(offset, &oi->rde_cb.offset, sizeof(offset));
424 oi->rde_cb.offsets = ARRAYSIZE(offset);
425 oi->rde_cb.width = 15;
426 oi->rde_cb.val_shift = 11;
427 oi->rde_cb.stat_shift = 16;
429 else if (sih->ccrev == 27) {
430 uint16 offset[] = {128, 143, 158, 173};
431 bcopy(offset, &oi->rde_cb.offset, sizeof(offset));
432 oi->rde_cb.offsets = ARRAYSIZE(offset);
433 oi->rde_cb.width = 15;
434 oi->rde_cb.val_shift = 11;
435 oi->rde_cb.stat_shift = 20;
437 else {
438 uint16 offset[] = {141, 158, 175, 205, 222, 239, 269, 286, 303};
439 bcopy(offset, &oi->rde_cb.offset, sizeof(offset));
440 oi->rde_cb.offsets = ARRAYSIZE(offset);
441 oi->rde_cb.width = 17;
442 oi->rde_cb.val_shift = 13;
443 oi->rde_cb.stat_shift = 16;
445 ASSERT(oi->rde_cb.offsets <= MAXNUMRDES);
446 #endif /* BCMNVRAMW */
448 /* Retrieve OTP region info */
449 idx = si_coreidx(sih);
450 cc = si_setcoreidx(sih, SI_CC_IDX);
451 ASSERT(cc != NULL);
453 _ipxotp_init(oi, cc);
455 si_setcoreidx(sih, idx);
457 return (void *)oi;
460 static int
461 ipxotp_read_region(void *oh, int region, uint16 *data, uint *wlen)
463 otpinfo_t *oi = (otpinfo_t *)oh;
464 uint idx;
465 chipcregs_t *cc;
466 uint base, i, sz;
468 /* Validate region selection */
469 switch (region) {
470 case OTP_HW_RGN:
471 sz = (uint)oi->hwlim - oi->hwbase;
472 if (!(oi->status & OTPS_GUP_HW)) {
473 OTP_ERR(("%s: h/w region not programmed\n", __FUNCTION__));
474 *wlen = sz;
475 return BCME_NOTFOUND;
477 if (*wlen < sz) {
478 OTP_ERR(("%s: buffer too small, should be at least %u\n",
479 __FUNCTION__, oi->hwlim - oi->hwbase));
480 *wlen = sz;
481 return BCME_BUFTOOSHORT;
483 base = oi->hwbase;
484 break;
485 case OTP_SW_RGN:
486 sz = ((uint)oi->swlim - oi->swbase);
487 if (!(oi->status & OTPS_GUP_SW)) {
488 OTP_ERR(("%s: s/w region not programmed\n", __FUNCTION__));
489 *wlen = sz;
490 return BCME_NOTFOUND;
492 if (*wlen < sz) {
493 OTP_ERR(("%s: buffer too small should be at least %u\n",
494 __FUNCTION__, oi->swlim - oi->swbase));
495 *wlen = sz;
496 return BCME_BUFTOOSHORT;
498 base = oi->swbase;
499 break;
500 case OTP_CI_RGN:
501 sz = OTPGU_CI_SZ;
502 if (!(oi->status & OTPS_GUP_CI)) {
503 OTP_ERR(("%s: chipid region not programmed\n", __FUNCTION__));
504 *wlen = sz;
505 return BCME_NOTFOUND;
507 if (*wlen < sz) {
508 OTP_ERR(("%s: buffer too small, should be at least %u\n",
509 __FUNCTION__, OTPGU_CI_SZ));
510 *wlen = sz;
511 return BCME_BUFTOOSHORT;
513 base = oi->otpgu_base + OTPGU_CI_OFF;
514 break;
515 case OTP_FUSE_RGN:
516 sz = (uint)oi->flim - oi->fbase;
517 if (!(oi->status & OTPS_GUP_FUSE)) {
518 OTP_ERR(("%s: fuse region not programmed\n", __FUNCTION__));
519 *wlen = sz;
520 return BCME_NOTFOUND;
522 if (*wlen < sz) {
523 OTP_ERR(("%s: buffer too small, should be at least %u\n",
524 __FUNCTION__, oi->flim - oi->fbase));
525 *wlen = sz;
526 return BCME_BUFTOOSHORT;
528 base = oi->fbase;
529 break;
530 default:
531 OTP_ERR(("%s: reading region %d is not supported\n", __FUNCTION__, region));
532 return BCME_BADARG;
535 idx = si_coreidx(oi->sih);
536 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
537 ASSERT(cc != NULL);
539 /* Read the data */
540 for (i = 0; i < sz; i ++)
541 data[i] = ipxotp_otpr(oh, cc, base + i);
543 si_setcoreidx(oi->sih, idx);
544 *wlen = sz;
545 return 0;
548 static int
549 ipxotp_nvread(void *oh, char *data, uint *len)
551 return BCME_UNSUPPORTED;
554 #ifdef BCMNVRAMW
555 static int
556 ipxotp_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off)
558 uint k, row, col;
559 uint32 otpp, st;
561 row = off / oi->cols;
562 col = off % oi->cols;
564 otpp = OTPP_START_BUSY |
565 ((1 << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) |
566 ((OTPPOC_BIT_PROG << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
567 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
568 ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
569 OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n",
570 __FUNCTION__, off, row, col, otpp));
571 W_REG(oi->osh, &cc->otpprog, otpp);
573 for (k = 0;
574 ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES);
575 k ++)
577 if (k >= OTPP_TRIES) {
578 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
579 return -1;
582 return 0;
585 static int
586 ipxotp_otpwb16(otpinfo_t *oi, chipcregs_t *cc, int wn, uint16 data)
588 uint base, i;
589 int rc = 0;
591 base = wn * 16;
592 for (i = 0; i < 16; i++) {
593 if (data & (1 << i)) {
594 if ((rc = ipxotp_write_bit(oi, cc, base + i)))
595 break;
599 return rc;
602 /* Write OTP redundancy entry:
603 * rde - redundancy entry index (-ve for "next")
604 * bit - bit offset
605 * val - bit value
608 ipxotp_write_rde(void *oh, int rde, uint bit, uint val)
610 otpinfo_t *oi = (otpinfo_t *)oh;
611 uint idx;
612 chipcregs_t *cc;
613 uint i, temp;
615 #ifdef BCMCBG
616 if ((rde >= oi->rde_cb.offsets) || (bit >= oi->rows * oi->cols) || (val > 1))
617 return BCME_RANGE;
618 #endif
620 if (rde < 0) {
621 for (rde = 0; rde < oi->rde_cb.offsets - 1; rde++) {
622 if ((oi->status & (1 << (oi->rde_cb.stat_shift + rde))) == 0)
623 break;
625 OTP_MSG(("%s: Auto rde index %d\n", __FUNCTION__, rde));
628 if (oi->status & (1 << (oi->rde_cb.stat_shift + rde))) {
629 OTP_MSG(("%s: rde %d already in use, status 0x%08x\n", __FUNCTION__,
630 rde, oi->status));
631 return BCME_ERROR;
634 idx = si_coreidx(oi->sih);
635 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
636 ASSERT(cc != NULL);
638 temp = ~(~0 << oi->rde_cb.width) &
639 ((~0 << (oi->rde_cb.val_shift + 1)) | (val << oi->rde_cb.val_shift) | bit);
641 OTP_MSG(("%s: rde %d bit %d val %d bmp 0x%08x\n", __FUNCTION__, rde, bit, val, temp));
643 /* Enable Write */
644 OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
646 for (i = 0; i < oi->rde_cb.width; i ++) {
647 if (!(temp & (1 << i)))
648 continue;
649 ipxotp_write_bit(oi, cc, oi->rde_cb.offset[rde] + i);
652 /* Disable Write */
653 AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
655 si_otp_power(oi->sih, FALSE);
656 si_otp_power(oi->sih, TRUE);
657 _ipxotp_init(oi, cc);
659 si_setcoreidx(oi->sih, idx);
660 return BCME_OK;
663 /* Set up redundancy entries for the specified bits */
664 static int
665 ipxotp_fix_word16(void *oh, uint wn, uint16 mask, uint16 val)
667 otpinfo_t *oi;
668 uint bit;
669 int rc = 0;
671 oi = (otpinfo_t *)oh;
673 ASSERT(oi != NULL);
674 ASSERT(wn < oi->wsize);
676 for (bit = wn * 16; mask; bit++, mask >>= 1, val >>= 1) {
677 if (mask & 1) {
678 if ((rc = ipxotp_write_rde(oi, -1, bit, val & 1)))
679 break;
683 return rc;
686 static int
687 ipxotp_check_word16(void *oh, chipcregs_t *cc, uint wn, uint16 val)
689 otpinfo_t *oi = (otpinfo_t *)oh;
690 uint16 word = ipxotp_otpr(oi, cc, wn);
691 int rc = 0;
693 if ((word ^= val)) {
694 OTP_MSG(("%s: word %d is 0x%04x, wanted 0x%04x, fixing...\n",
695 __FUNCTION__, wn, (word ^ val), val));
696 if ((rc = ipxotp_fix_word16(oi, wn, word, val))) {
697 OTP_ERR(("FAILED, ipxotp_fix_word16 returns %d\n", rc));
698 /* Fatal error, unfixable. MFGC will have to fail. Board
699 * needs to be discarded!!
701 return BCME_NORESOURCE;
705 return BCME_OK;
709 /* expects the caller to disable interrupts before calling this routine */
710 static int
711 ipxotp_write_region(void *oh, int region, uint16 *data, uint wlen)
713 otpinfo_t *oi = (otpinfo_t *)oh;
714 uint idx;
715 chipcregs_t *cc;
716 uint base, i;
717 int otpgu_bit_base;
718 bool rewrite = FALSE;
719 int rc = 0;
720 uint16 *origdata = NULL;
722 otpgu_bit_base = oi->otpgu_base * 16;
724 /* Validate region selection */
725 switch (region) {
726 case OTP_HW_RGN:
727 if (wlen > (uint)(oi->hwlim - oi->hwbase)) {
728 OTP_ERR(("%s: wlen %u exceeds OTP h/w region limit %u\n",
729 __FUNCTION__, wlen, oi->hwlim - oi->hwbase));
730 return BCME_BUFTOOLONG;
732 rewrite = !!(oi->status & OTPS_GUP_HW);
733 base = oi->hwbase;
734 break;
735 case OTP_SW_RGN:
736 if (wlen > (uint)(oi->swlim - oi->swbase)) {
737 OTP_ERR(("%s: wlen %u exceeds OTP s/w region limit %u\n",
738 __FUNCTION__, wlen, oi->swlim - oi->swbase));
739 return BCME_BUFTOOLONG;
741 rewrite = !!(oi->status & OTPS_GUP_SW);
742 base = oi->swbase;
743 break;
744 case OTP_CI_RGN:
745 if (oi->status & OTPS_GUP_CI) {
746 OTP_ERR(("%s: chipid region has been programmed\n", __FUNCTION__));
747 return BCME_ERROR;
749 if (wlen > OTPGU_CI_SZ) {
750 OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n",
751 __FUNCTION__, wlen, OTPGU_CI_SZ));
752 return BCME_BUFTOOLONG;
754 if ((wlen == OTPGU_CI_SZ) && (data[OTPGU_CI_SZ - 1] & OTPGU_P_MSK) != 0) {
755 OTP_ERR(("%s: subregion programmed bits not zero\n", __FUNCTION__));
756 return BCME_BADARG;
758 base = oi->otpgu_base + OTPGU_CI_OFF;
759 break;
760 case OTP_FUSE_RGN:
761 if (oi->status & OTPS_GUP_FUSE) {
762 OTP_ERR(("%s: fuse region has been programmed\n", __FUNCTION__));
763 return BCME_ERROR;
765 if (wlen > (uint)(oi->flim - oi->fbase)) {
766 OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n",
767 __FUNCTION__, wlen, oi->flim - oi->fbase));
768 return BCME_BUFTOOLONG;
770 base = oi->flim - wlen;
771 break;
772 default:
773 OTP_ERR(("%s: writing region %d is not supported\n", __FUNCTION__, region));
774 return BCME_ERROR;
777 idx = si_coreidx(oi->sih);
778 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
779 ASSERT(cc != NULL);
781 /* Check for conflict; Since some bits might be programmed at ATE time, we need to
782 * avoid redundancy by clearing already written bits, but copy original for verification.
784 if ((origdata = (uint16*)MALLOC(oi->osh, wlen * 2)) == NULL) {
785 rc = BCME_NOMEM;
786 goto exit;
788 for (i = 0; i < wlen; i++) {
789 origdata[i] = data[i];
790 data[i] = ipxotp_otpr(oi, cc, base + i);
791 if (data[i] & ~origdata[i]) {
792 OTP_ERR(("%s: %s region: word %d incompatible (0x%04x->0x%04x)\n",
793 __FUNCTION__, HWSW_RGN(region), i, data[i], origdata[i]));
794 rc = BCME_BADARG;
795 goto exit;
797 data[i] ^= origdata[i];
799 OTP_MSG(("%s: writing new bits in %s region\n", __FUNCTION__, HWSW_RGN(region)));
801 /* Enable Write */
802 OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN);
804 /* Write the data */
805 for (i = 0; i < wlen; i++) {
806 ipxotp_otpwb16(oi, cc, base + i, data[i]);
809 /* One time set region flag: Update boundary/flag in memory and in OTP */
810 if (!rewrite) {
811 switch (region) {
812 case OTP_HW_RGN:
813 ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, (base + i) * 16);
814 ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_HWP_OFF);
815 break;
816 case OTP_SW_RGN:
817 /* Write HW region limit as well */
818 ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, base * 16);
819 /* write max swlim(covert to bits) to the sw/fuse boundary */
820 ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, oi->swlim * 16);
821 ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_SWP_OFF);
822 break;
823 case OTP_CI_RGN:
824 ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_CIP_OFF);
825 /* Also set the OTPGU_CIP_MSK bit in the input so verification
826 * doesn't fail
828 if (wlen >= OTPGU_CI_SZ)
829 data[OTPGU_CI_SZ - 1] |= OTPGU_CIP_MSK;
830 break;
831 case OTP_FUSE_RGN:
832 ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, base * 16);
833 ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_FUSEP_OFF);
834 break;
838 /* Disable Write */
839 AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN);
841 /* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */
842 si_otp_power(oi->sih, FALSE);
843 si_otp_power(oi->sih, TRUE);
845 /* Check and fix for region size and region programmed bits */
846 if (!rewrite) {
847 uint16 boundary_off = 0, boundary_val = 0;
848 uint16 programmed_off = 0;
849 uint16 bit = 0;
851 switch (region) {
852 case OTP_HW_RGN:
853 boundary_off = OTPGU_HSB_OFF;
854 boundary_val = (base + i) * 16;
855 programmed_off = OTPGU_HWP_OFF;
856 break;
857 case OTP_SW_RGN:
858 /* Also write 0 to HW region boundary */
859 if ((rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF,
860 base * 16)))
861 goto exit;
862 boundary_off = OTPGU_SFB_OFF;
863 boundary_val = oi->swlim * 16;
864 programmed_off = OTPGU_SWP_OFF;
865 break;
866 case OTP_CI_RGN:
867 /* No CI region boundary */
868 programmed_off = OTPGU_CIP_OFF;
869 break;
870 case OTP_FUSE_RGN:
871 boundary_off = OTPGU_SFB_OFF;
872 boundary_val = base * 16;
873 programmed_off = OTPGU_FUSEP_OFF;
874 break;
877 /* Do the actual checking and return BCME_NORESOURCE if we cannot fix */
878 if ((region != OTP_CI_RGN) &&
879 (rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + boundary_off,
880 boundary_val))) {
881 goto exit;
884 if ((bit = ipxotp_read_bit(oh, cc, otpgu_bit_base + programmed_off)) == 0xffff) {
885 OTP_ERR(("\n%s: FAILED bit %d reads %d\n", __FUNCTION__, otpgu_bit_base +
886 programmed_off, bit));
887 goto exit;
888 } else if (bit == 0) { /* error detected, fix it */
889 OTP_ERR(("\n%s: FAILED bit %d reads %d, fixing\n", __FUNCTION__,
890 otpgu_bit_base + programmed_off, bit));
891 if ((rc = ipxotp_write_rde(oi, -1, otpgu_bit_base + programmed_off, 1))) {
892 OTP_ERR(("\n%s: cannot fix, ipxotp_write_rde returns %d\n",
893 __FUNCTION__, rc));
894 goto exit;
899 /* Update status, apply WAR */
900 _ipxotp_init(oi, cc);
902 /* Recover original data... */
903 if (origdata)
904 bcopy(origdata, data, wlen * 2);
906 /* ...so we can verify and fix where possible */
907 for (i = 0; i < wlen; i++) {
908 if ((rc = ipxotp_check_word16(oi, cc, base + i, data[i])))
909 goto exit;
912 exit:
913 if (origdata)
914 MFREE(oi->osh, origdata, wlen * 2);
916 si_setcoreidx(oi->sih, idx);
917 return rc;
920 static int
921 ipxotp_cis_append_region(si_t *sih, int region, char *vars, int count)
923 uint8 *cis;
924 osl_t *osh;
925 uint sz = OTP_SZ_MAX/2; /* size in words */
926 int rc = 0;
927 bool newchip = FALSE;
929 ASSERT(region == OTP_HW_RGN || region == OTP_SW_RGN);
931 osh = si_osh(sih);
932 if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) {
933 return BCME_ERROR;
936 bzero(cis, OTP_SZ_MAX);
938 rc = otp_read_region(sih, region, (uint16 *)cis, &sz);
939 newchip = (rc == BCME_NOTFOUND) ? TRUE : FALSE;
940 rc = 0;
942 /* zero count for read, non-zero count for write */
943 if (count) {
944 int i = 0, newlen = 0;
946 if (newchip) {
947 int termw_len = 0; /* length of termination word */
949 /* convert halfwords to bytes offset */
950 newlen = sz * 2;
952 if ((CHIPID(sih->chip) == BCM4322_CHIP_ID) ||
953 (CHIPID(sih->chip) == BCM43231_CHIP_ID) ||
954 1) {
955 /* bootloader WAR, refer to above twiki link */
956 cis[newlen-1] = 0x00;
957 cis[newlen-2] = 0xff;
958 cis[newlen-3] = 0x00;
959 cis[newlen-4] = 0xff;
960 cis[newlen-5] = 0xff;
961 cis[newlen-6] = 0x1;
962 cis[newlen-7] = 0x2;
963 termw_len = 7;
964 } else {
965 cis[newlen-1] = 0xff;
966 cis[newlen-2] = 0xff;
967 termw_len = 2;
970 if (count >= newlen - termw_len) {
971 OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", newlen, count));
972 rc = BCME_BUFTOOLONG;
974 } else {
975 int end = 0;
977 /* Walk through the leading zeros (could be 0 or 8 bytes for now) */
978 for (i = 0; i < (int)sz*2; i++)
979 if (cis[i] != 0)
980 break;
982 /* Find the place to append */
983 for (; i < (int)sz*2; i++) {
984 if (cis[i] == 0)
985 break;
986 i += ((int)cis[i+1] + 1);
989 for (end = i; end < (int)sz*2; end++) {
990 if (cis[end] != 0)
991 break;
994 newlen = i + count;
995 if (newlen & 1) /* make it even-sized buffer */
996 newlen++;
998 if (newlen >= (end - 1)) {
999 OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", end-i, count));
1000 rc = BCME_BUFTOOLONG;
1004 /* copy the buffer */
1005 memcpy(&cis[i], vars, count);
1006 #ifdef BCMNVRAMW
1007 /* Write the buffer back */
1008 if (!rc)
1009 rc = otp_write_region(sih, region, (uint16*)cis, newlen/2);
1011 /* Print the buffer */
1012 OTP_MSG(("Buffer of size %d bytes to write:\n", newlen));
1013 for (i = 0; i < newlen; i++) {
1014 OTP_DBG(("%02x ", cis[i] & 0xff));
1015 if ((i % 16) == 15) {
1016 OTP_DBG(("\n"));
1019 OTP_MSG(("\n"));
1020 #endif /* BCMNVRAMW */
1023 if (cis)
1024 MFREE(osh, cis, OTP_SZ_MAX);
1026 return (rc);
1029 /* No need to lock for IPXOTP. HNDOTP needs it due to the randomness of unprogrammed
1030 * content
1032 static int
1033 ipxotp_lock(void *oh)
1035 return 0;
1038 static int
1039 ipxotp_nvwrite(void *oh, uint16 *data, uint wlen)
1041 return -1;
1043 #endif /* BCMNVRAMW */
1045 #if defined(WLTEST)
1046 static uint16
1047 ipxotp_otprb16(void *oh, chipcregs_t *cc, uint wn)
1049 uint base, i;
1050 uint16 val;
1051 uint16 bit;
1053 base = wn * 16;
1055 val = 0;
1056 for (i = 0; i < 16; i++) {
1057 if ((bit = ipxotp_read_bit(oh, cc, base + i)) == 0xffff)
1058 break;
1059 val = val | (bit << i);
1061 if (i < 16)
1062 val = 0xffff;
1064 return val;
1067 static int
1068 ipxotp_dump(void *oh, int arg, char *buf, uint size)
1070 otpinfo_t *oi = (otpinfo_t *)oh;
1071 chipcregs_t *cc;
1072 uint idx, i, count;
1073 uint16 val;
1074 struct bcmstrbuf b;
1076 idx = si_coreidx(oi->sih);
1077 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1078 ASSERT(cc != NULL);
1080 count = ipxotp_size(oh);
1082 bcm_binit(&b, buf, size);
1083 for (i = 0; i < count / 2; i++) {
1084 if (!(i % 4))
1085 bcm_bprintf(&b, "\n0x%04x:", 2 * i);
1086 if (arg == 0)
1087 val = ipxotp_otpr(oh, cc, i);
1088 else
1089 val = ipxotp_otprb16(oi, cc, i);
1090 bcm_bprintf(&b, " 0x%04x", val);
1092 bcm_bprintf(&b, "\n");
1094 si_setcoreidx(oi->sih, idx);
1096 return ((int)(b.buf - b.origbuf));
1098 #endif
1100 static otp_fn_t ipxotp_fn = {
1101 (otp_status_t)ipxotp_status,
1102 (otp_size_t)ipxotp_size,
1103 (otp_read_bit_t)ipxotp_read_bit,
1104 (otp_init_t)ipxotp_init,
1105 (otp_read_region_t)ipxotp_read_region,
1106 (otp_nvread_t)ipxotp_nvread,
1107 #ifdef BCMNVRAMW
1108 (otp_write_region_t)ipxotp_write_region,
1109 (otp_cis_append_region_t)ipxotp_cis_append_region,
1110 (otp_lock_t)ipxotp_lock,
1111 (otp_nvwrite_t)ipxotp_nvwrite,
1112 #endif /* BCMNVRAMW */
1113 #if defined(WLTEST)
1114 (otp_dump_t)ipxotp_dump,
1115 #endif
1116 OTP_FN_MAGIC
1119 #endif /* BCMAUTOOTP || !BCMHNDOTP */
1123 * HND OTP Code: Compiled for HND OTP or AUTO mode
1124 * Exported functions:
1125 * hndotp_status()
1126 * hndotp_size()
1127 * hndotp_init()
1128 * hndotp_read_bit()
1129 * hndotp_read_region()
1130 * hndotp_nvread()
1131 * hndotp_write_region()
1132 * hndotp_cis_append_region()
1133 * hndotp_lock()
1134 * hndotp_nvwrite()
1135 * hndotp_dump()
1137 * HND internal functions:
1138 * hndotp_otpr()
1139 * hndotp_otproff()
1140 * hndotp_write_bit()
1141 * hndotp_write_word()
1142 * hndotp_valid_rce()
1143 * hndotp_write_rce()
1144 * hndotp_write_row()
1145 * hndotp_otprb16()
1149 #if defined(BCMAUTOOTP) || defined(BCMHNDOTP) /* Older HND OTP wrapper */
1151 /* Fields in otpstatus */
1152 #define OTPS_PROGFAIL 0x80000000
1153 #define OTPS_PROTECT 0x00000007
1154 #define OTPS_HW_PROTECT 0x00000001
1155 #define OTPS_SW_PROTECT 0x00000002
1156 #define OTPS_CID_PROTECT 0x00000004
1157 #define OTPS_RCEV_MSK 0x00003f00
1158 #define OTPS_RCEV_SHIFT 8
1160 /* Fields in the otpcontrol register */
1161 #define OTPC_RECWAIT 0xff000000
1162 #define OTPC_PROGWAIT 0x00ffff00
1163 #define OTPC_PRW_SHIFT 8
1164 #define OTPC_MAXFAIL 0x00000038
1165 #define OTPC_VSEL 0x00000006
1166 #define OTPC_SELVL 0x00000001
1168 /* OTP regions (Word offsets from otp size) */
1169 #define OTP_SWLIM_OFF (-4)
1170 #define OTP_CIDBASE_OFF 0
1171 #define OTP_CIDLIM_OFF 4
1173 /* Predefined OTP words (Word offset from otp size) */
1174 #define OTP_BOUNDARY_OFF (-4)
1175 #define OTP_HWSIGN_OFF (-3)
1176 #define OTP_SWSIGN_OFF (-2)
1177 #define OTP_CIDSIGN_OFF (-1)
1178 #define OTP_CID_OFF 0
1179 #define OTP_PKG_OFF 1
1180 #define OTP_FID_OFF 2
1181 #define OTP_RSV_OFF 3
1182 #define OTP_LIM_OFF 4
1183 #define OTP_RD_OFF 4 /* Redundancy row starts here */
1184 #define OTP_RC0_OFF 28 /* Redundancy control word 1 */
1185 #define OTP_RC1_OFF 32 /* Redundancy control word 2 */
1186 #define OTP_RC_LIM_OFF 36 /* Redundancy control word end */
1188 #define OTP_HW_REGION OTPS_HW_PROTECT
1189 #define OTP_SW_REGION OTPS_SW_PROTECT
1190 #define OTP_CID_REGION OTPS_CID_PROTECT
1192 #if OTP_HW_REGION != OTP_HW_RGN
1193 #error "incompatible OTP_HW_RGN"
1194 #endif
1195 #if OTP_SW_REGION != OTP_SW_RGN
1196 #error "incompatible OTP_SW_RGN"
1197 #endif
1198 #if OTP_CID_REGION != OTP_CI_RGN
1199 #error "incompatible OTP_CI_RGN"
1200 #endif
1202 /* Redundancy entry definitions */
1203 #define OTP_RCE_ROW_SZ 6
1204 #define OTP_RCE_SIGN_MASK 0x7fff
1205 #define OTP_RCE_ROW_MASK 0x3f
1206 #define OTP_RCE_BITS 21
1207 #define OTP_RCE_SIGN_SZ 15
1208 #define OTP_RCE_BIT0 1
1210 #define OTP_WPR 4
1211 #define OTP_SIGNATURE 0x578a
1212 #define OTP_MAGIC 0x4e56
1214 static int
1215 hndotp_status(void *oh)
1217 otpinfo_t *oi = (otpinfo_t *)oh;
1218 return ((int)(oi->hwprot | oi->signvalid));
1221 static int
1222 hndotp_size(void *oh)
1224 otpinfo_t *oi = (otpinfo_t *)oh;
1225 return ((int)(oi->size));
1228 static uint16
1229 hndotp_otpr(void *oh, chipcregs_t *cc, uint wn)
1231 otpinfo_t *oi = (otpinfo_t *)oh;
1232 osl_t *osh;
1233 uint16 *ptr;
1235 ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF));
1236 ASSERT(cc);
1238 osh = si_osh(oi->sih);
1240 ptr = (uint16 *)((uchar *)cc + CC_SROM_OTP);
1241 return (R_REG(osh, &ptr[wn]));
1244 static uint16
1245 hndotp_otproff(void *oh, chipcregs_t *cc, int woff)
1247 otpinfo_t *oi = (otpinfo_t *)oh;
1248 osl_t *osh;
1249 uint16 *ptr;
1251 ASSERT(woff >= (-((int)oi->size / 2)));
1252 ASSERT(woff < OTP_LIM_OFF);
1253 ASSERT(cc);
1255 osh = si_osh(oi->sih);
1257 ptr = (uint16 *)((uchar *)cc + CC_SROM_OTP);
1259 return (R_REG(osh, &ptr[(oi->size / 2) + woff]));
1262 static uint16
1263 hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx)
1265 otpinfo_t *oi = (otpinfo_t *)oh;
1266 uint k, row, col;
1267 uint32 otpp, st;
1268 osl_t *osh;
1270 osh = si_osh(oi->sih);
1271 row = idx / 65;
1272 col = idx % 65;
1274 otpp = OTPP_START_BUSY | OTPP_READ |
1275 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
1276 (col & OTPP_COL_MASK);
1278 OTP_DBG(("%s: idx = %d, row = %d, col = %d, otpp = 0x%x", __FUNCTION__,
1279 idx, row, col, otpp));
1281 W_REG(osh, &cc->otpprog, otpp);
1282 st = R_REG(osh, &cc->otpprog);
1283 for (k = 0; ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
1284 st = R_REG(osh, &cc->otpprog);
1286 if (k >= OTPP_TRIES) {
1287 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k));
1288 return 0xffff;
1290 if (st & OTPP_READERR) {
1291 OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, idx));
1292 return 0xffff;
1294 st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
1295 OTP_DBG((" => %d\n", st));
1296 return (uint16)st;
1299 static void*
1300 BCMNMIATTACHFN(hndotp_init)(si_t *sih)
1302 uint idx;
1303 chipcregs_t *cc;
1304 otpinfo_t *oi;
1305 uint32 cap = 0, clkdiv, otpdiv = 0;
1306 void *ret = NULL;
1307 osl_t *osh;
1309 OTP_MSG(("%s: Use HND OTP controller\n", __FUNCTION__));
1310 oi = &otpinfo;
1312 idx = si_coreidx(sih);
1313 osh = si_osh(oi->sih);
1315 /* Check for otp */
1316 if ((cc = si_setcoreidx(sih, SI_CC_IDX)) != NULL) {
1317 cap = R_REG(osh, &cc->capabilities);
1318 if ((cap & CC_CAP_OTPSIZE) == 0) {
1319 /* Nothing there */
1320 goto out;
1323 /* As of right now, support only 4320a2, 4311a1 and 4312 */
1324 ASSERT((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22));
1325 if (!((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22)))
1326 return NULL;
1328 /* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is
1329 * 8 row (64 bytes) smaller
1331 oi->size = 1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT)
1332 + CC_CAP_OTPSIZE_BASE);
1333 if (oi->ccrev >= 18)
1334 oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2);
1336 oi->hwprot = (int)(R_REG(osh, &cc->otpstatus) & OTPS_PROTECT);
1337 oi->boundary = -1;
1339 /* Check the region signature */
1340 if (hndotp_otproff(oi, cc, OTP_HWSIGN_OFF) == OTP_SIGNATURE) {
1341 oi->signvalid |= OTP_HW_REGION;
1342 oi->boundary = hndotp_otproff(oi, cc, OTP_BOUNDARY_OFF);
1345 if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE)
1346 oi->signvalid |= OTP_SW_REGION;
1348 if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE)
1349 oi->signvalid |= OTP_CID_REGION;
1351 /* Set OTP clkdiv for stability */
1352 if (oi->ccrev == 22)
1353 otpdiv = 12;
1355 if (otpdiv) {
1356 clkdiv = R_REG(osh, &cc->clkdiv);
1357 clkdiv = (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT);
1358 W_REG(osh, &cc->clkdiv, clkdiv);
1359 OTP_MSG(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
1361 OSL_DELAY(10);
1363 ret = (void *)oi;
1366 OTP_MSG(("%s: ccrev %d\tsize %d bytes\thwprot %x\tsignvalid %x\tboundary %x\n",
1367 __FUNCTION__, oi->ccrev, oi->size, oi->hwprot, oi->signvalid,
1368 oi->boundary));
1370 out: /* All done */
1371 si_setcoreidx(sih, idx);
1373 return ret;
1376 static int
1377 hndotp_read_region(void *oh, int region, uint16 *data, uint *wlen)
1379 otpinfo_t *oi = (otpinfo_t *)oh;
1380 uint32 idx, st;
1381 chipcregs_t *cc;
1382 int i;
1384 /* Only support HW region (no active chips use HND OTP SW region) */
1385 ASSERT(region == OTP_HW_REGION);
1387 OTP_MSG(("%s: region %x wlen %d\n", __FUNCTION__, region, *wlen));
1389 /* Region empty? */
1390 st = oi->hwprot | oi-> signvalid;
1391 if ((st & region) == 0)
1392 return BCME_NOTFOUND;
1394 *wlen = ((int)*wlen < oi->boundary/2) ? *wlen : (uint)oi->boundary/2;
1396 idx = si_coreidx(oi->sih);
1397 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1398 ASSERT(cc != NULL);
1400 for (i = 0; i < (int)*wlen; i++)
1401 data[i] = hndotp_otpr(oh, cc, i);
1403 si_setcoreidx(oi->sih, idx);
1405 return 0;
1408 static int
1409 hndotp_nvread(void *oh, char *data, uint *len)
1411 int rc = 0;
1412 otpinfo_t *oi = (otpinfo_t *)oh;
1413 uint32 base, bound, lim = 0, st;
1414 int i, chunk, gchunks, tsz = 0;
1415 uint32 idx;
1416 chipcregs_t *cc;
1417 uint offset;
1418 uint16 *rawotp = NULL;
1420 /* save the orig core */
1421 idx = si_coreidx(oi->sih);
1422 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1423 ASSERT(cc != NULL);
1425 st = hndotp_status(oh);
1426 if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) {
1427 OTP_ERR(("OTP not programmed\n"));
1428 rc = -1;
1429 goto out;
1432 /* Read the whole otp so we can easily manipulate it */
1433 lim = hndotp_size(oh);
1434 if ((rawotp = MALLOC(si_osh(oi->sih), lim)) == NULL) {
1435 OTP_ERR(("Out of memory for rawotp\n"));
1436 rc = -2;
1437 goto out;
1439 for (i = 0; i < (int)(lim / 2); i++)
1440 rawotp[i] = hndotp_otpr(oh, cc, i);
1442 if ((st & OTP_HW_REGION) == 0) {
1443 OTP_ERR(("otp: hw region not written (0x%x)\n", st));
1445 /* This could be a programming failure in the first
1446 * chunk followed by one or more good chunks
1448 for (i = 0; i < (int)(lim / 2); i++)
1449 if (rawotp[i] == OTP_MAGIC)
1450 break;
1452 if (i < (int)(lim / 2)) {
1453 base = i;
1454 bound = (i * 2) + rawotp[i + 1];
1455 OTP_MSG(("otp: trying chunk at 0x%x-0x%x\n", i * 2, bound));
1456 } else {
1457 OTP_MSG(("otp: unprogrammed\n"));
1458 rc = -3;
1459 goto out;
1461 } else {
1462 bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF];
1464 /* There are two cases: 1) The whole otp is used as nvram
1465 * and 2) There is a hardware header followed by nvram.
1467 if (rawotp[0] == OTP_MAGIC) {
1468 base = 0;
1469 if (bound != rawotp[1])
1470 OTP_MSG(("otp: Bound 0x%x != chunk0 len 0x%x\n", bound,
1471 rawotp[1]));
1472 } else
1473 base = bound;
1476 /* Find and copy the data */
1478 chunk = 0;
1479 gchunks = 0;
1480 i = base / 2;
1481 offset = 0;
1482 while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) {
1483 int dsz, rsz = rawotp[i + 1];
1485 if (((i * 2) + rsz) >= (int)lim) {
1486 OTP_MSG((" bad chunk size, chunk %d, base 0x%x, size 0x%x\n",
1487 chunk, i * 2, rsz));
1488 /* Bad length, try to find another chunk anyway */
1489 rsz = 6;
1491 if (hndcrc16((uint8 *)&rawotp[i], rsz,
1492 CRC16_INIT_VALUE) == CRC16_GOOD_VALUE) {
1493 /* Good crc, copy the vars */
1494 OTP_MSG((" good chunk %d, base 0x%x, size 0x%x\n",
1495 chunk, i * 2, rsz));
1496 gchunks++;
1497 dsz = rsz - 6;
1498 tsz += dsz;
1499 if (offset + dsz >= *len) {
1500 OTP_MSG(("Out of memory for otp\n"));
1501 goto out;
1503 bcopy((char *)&rawotp[i + 2], &data[offset], dsz);
1504 offset += dsz;
1505 /* Remove extra null characters at the end */
1506 while (offset > 1 &&
1507 data[offset - 1] == 0 && data[offset - 2] == 0)
1508 offset --;
1509 i += rsz / 2;
1510 } else {
1511 /* bad length or crc didn't check, try to find the next set */
1512 OTP_MSG((" chunk %d @ 0x%x size 0x%x: bad crc, ",
1513 chunk, i * 2, rsz));
1514 if (rawotp[i + (rsz / 2)] == OTP_MAGIC) {
1515 /* Assume length is good */
1516 i += rsz / 2;
1517 } else {
1518 while (++i < (int)(lim / 2))
1519 if (rawotp[i] == OTP_MAGIC)
1520 break;
1522 if (i < (int)(lim / 2))
1523 OTP_MSG(("trying next base 0x%x\n", i * 2));
1524 else
1525 OTP_MSG(("no more chunks\n"));
1527 chunk++;
1530 OTP_MSG((" otp size = %d, boundary = 0x%x, nv base = 0x%x\n", lim, bound, base));
1531 if (tsz != 0) {
1532 OTP_MSG((" Found %d bytes in %d good chunks out of %d\n", tsz, gchunks, chunk));
1533 } else {
1534 OTP_MSG((" No good chunks found out of %d\n", chunk));
1537 *len = offset;
1539 out:
1540 if (rawotp)
1541 MFREE(si_osh(oi->sih), rawotp, lim);
1542 si_setcoreidx(oi->sih, idx);
1544 return rc;
1547 #ifdef BCMNVRAMW
1548 #if defined(WLTEST)
1549 static uint st_n, st_s, st_hwm, pp_hwm;
1550 #ifdef OTP_FORCEFAIL
1551 static uint forcefail_bitcount = 0;
1552 #endif /* OTP_FORCEFAIL */
1553 #endif
1555 static int
1556 hndotp_write_bit(void *oh, chipcregs_t *cc, int bn, bool bit, int no_retry)
1558 otpinfo_t *oi = (otpinfo_t *)oh;
1559 uint row, col, j, k;
1560 uint32 pwait, init_pwait, otpc, otpp, pst, st;
1561 osl_t *osh;
1563 osh = si_osh(oi->sih);
1564 ASSERT((bit >> 1) == 0);
1566 #ifdef OTP_FORCEFAIL
1567 OTP_MSG(("%s: [0x%x] = 0x%x\n", __FUNCTION__, wn * 2, data));
1568 #endif
1570 /* This is bit-at-a-time writing, future cores may do word-at-a-time */
1571 if (oi->ccrev == 12) {
1572 otpc = 0x20000001;
1573 init_pwait = 0x00000200;
1574 } else if (oi->ccrev == 22) {
1575 otpc = 0x20000001;
1576 init_pwait = 0x00000400;
1577 } else {
1578 otpc = 0x20000001;
1579 init_pwait = 0x00004000;
1582 pwait = init_pwait;
1583 row = bn / 65;
1584 col = bn % 65;
1585 otpp = OTPP_START_BUSY |
1586 ((bit << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) |
1587 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
1588 (col & OTPP_COL_MASK);
1589 j = 0;
1590 while (1) {
1591 j++;
1592 if (j > 1) {
1593 OTP_DBG(("row %d, col %d, val %d, otpc 0x%x, otpp 0x%x\n",
1594 row, col, bit, (otpc | pwait), otpp));
1597 W_REG(osh, &cc->otpcontrol, otpc | pwait);
1598 W_REG(osh, &cc->otpprog, otpp);
1599 pst = R_REG(osh, &cc->otpprog);
1600 for (k = 0; ((pst & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
1601 pst = R_REG(osh, &cc->otpprog);
1602 #if defined(WLTEST)
1603 if (k > pp_hwm)
1604 pp_hwm = k;
1605 #endif
1606 if (k >= OTPP_TRIES) {
1607 OTP_ERR(("BUSY stuck: pst=0x%x, count=%d\n", pst, k));
1608 st = OTPS_PROGFAIL;
1609 break;
1611 st = R_REG(osh, &cc->otpstatus);
1612 if (((st & OTPS_PROGFAIL) == 0) || (pwait == OTPC_PROGWAIT) || (no_retry)) {
1613 break;
1614 } else {
1615 if ((oi->ccrev == 12) || (oi->ccrev == 22))
1616 pwait = (pwait << 3) & OTPC_PROGWAIT;
1617 else
1618 pwait = (pwait << 1) & OTPC_PROGWAIT;
1619 if (pwait == 0)
1620 pwait = OTPC_PROGWAIT;
1623 #if defined(WLTEST)
1624 st_n++;
1625 st_s += j;
1626 if (j > st_hwm)
1627 st_hwm = j;
1628 #ifdef OTP_FORCEFAIL
1629 if (forcefail_bitcount++ == OTP_FORCEFAIL * 16) {
1630 OTP_DBG(("Forcing PROGFAIL on bit %d (FORCEFAIL = %d/0x%x)\n",
1631 forcefail_bitcount, OTP_FORCEFAIL, OTP_FORCEFAIL));
1632 st = OTPS_PROGFAIL;
1634 #endif
1635 #endif
1636 if (st & OTPS_PROGFAIL) {
1637 OTP_ERR(("After %d tries: otpc = 0x%x, otpp = 0x%x/0x%x, otps = 0x%x\n",
1638 j, otpc | pwait, otpp, pst, st));
1639 OTP_ERR(("otp prog failed. bit=%d, ppret=%d, ret=%d\n", bit, k, j));
1640 return 1;
1643 return 0;
1646 static int
1647 hndotp_write_word(void *oh, chipcregs_t *cc, int wn, uint16 data)
1649 uint base, i;
1650 int err = 0;
1652 OTP_MSG(("%s: wn %d data %x\n", __FUNCTION__, wn, data));
1654 /* There is one test bit for each row */
1655 base = (wn * 16) + (wn / 4);
1657 for (i = 0; i < 16; i++) {
1658 err += hndotp_write_bit(oh, cc, base + i, data & 1, 0);
1659 data >>= 1;
1660 /* abort write after first error to avoid stress the charge-pump */
1661 if (err) {
1662 OTP_DBG(("%s: wn %d fail on bit %d\n", __FUNCTION__, wn, i));
1663 break;
1667 return err;
1670 static int
1671 hndotp_valid_rce(void *oh, chipcregs_t *cc, int i)
1673 otpinfo_t *oi = (otpinfo_t *)oh;
1674 osl_t *osh;
1675 uint32 hwv, fw, rce, e, sign, row, st;
1677 ASSERT(oi->ccrev >= 18);
1679 /* HW valid bit */
1680 osh = si_osh(oi->sih);
1681 st = R_REG(osh, &cc->otpstatus);
1682 hwv = (st & OTPS_RCEV_MSK) & (1 << (OTPS_RCEV_SHIFT + i));
1684 if (i < 3) {
1685 e = i;
1686 fw = hndotp_size(oh)/2 + OTP_RC0_OFF + e;
1687 } else {
1688 e = i - 3;
1689 fw = hndotp_size(oh)/2 + OTP_RC1_OFF + e;
1692 rce = hndotp_otpr(oh, cc, fw+1) << 16 | hndotp_otpr(oh, cc, fw);
1693 rce >>= ((e * OTP_RCE_BITS) + OTP_RCE_BIT0 - (e * 16));
1694 row = rce & OTP_RCE_ROW_MASK;
1695 sign = (rce >> OTP_RCE_ROW_SZ) & OTP_RCE_SIGN_MASK;
1697 OTP_MSG(("rce %d sign %x row %d hwv %x\n", i, sign, row, hwv));
1699 return (sign == OTP_SIGNATURE) ? row : -1;
1702 static int
1703 hndotp_write_rce(void *oh, chipcregs_t *cc, int r, uint16* data)
1705 int i, rce = -1;
1706 uint32 sign;
1708 ASSERT(((otpinfo_t *)oh)->ccrev >= 18);
1709 ASSERT(r >= 0 && r < hndotp_size(oh)/(2*OTP_WPR));
1710 ASSERT(data);
1712 for (rce = OTP_RCE_ROW_SZ -1; rce >= 0; rce--) {
1713 int e, rt, rcr, bit, err = 0;
1715 int rr = hndotp_valid_rce(oh, cc, rce);
1716 /* redundancy row in use already */
1717 if (rr != -1) {
1718 if (rr == r) {
1719 OTP_MSG(("%s: row %d already replaced by RCE %d",
1720 __FUNCTION__, r, rce));
1721 return 0;
1724 continue; /* If row used, go for the next row */
1728 * previously used bad rce entry maybe treaed as valid rce and used again, abort on
1729 * first bit error to avoid stress the charge pump
1732 /* Write the data to the redundant row */
1733 for (i = 0; i < OTP_WPR; i++) {
1734 err += hndotp_write_word(oh, cc, hndotp_size(oh)/2+OTP_RD_OFF+rce*4+i,
1735 data[i]);
1736 if (err) {
1737 OTP_MSG(("fail to write redundant row %d\n", rce));
1738 break;
1742 /* Now write the redundant row index */
1743 if (rce < 3) {
1744 e = rce;
1745 rcr = hndotp_size(oh)/2 + OTP_RC0_OFF;
1746 } else {
1747 e = rce - 3;
1748 rcr = hndotp_size(oh)/2 + OTP_RC1_OFF;
1751 /* Write row numer bit-by-bit */
1752 bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0;
1753 rt = r;
1754 for (i = 0; i < OTP_RCE_ROW_SZ; i++) {
1755 /* If any timeout happened, invalidate the subsequent bits with 0 */
1756 if (hndotp_write_bit(oh, cc, bit, (rt & (err ? 0 : 1)), err)) {
1757 OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row"
1758 " number bit %x\n", __FUNCTION__, r, rce, i));
1759 err++;
1761 rt >>= 1;
1762 bit ++;
1765 /* Write the RCE signature bit-by-bit */
1766 sign = OTP_SIGNATURE;
1767 for (i = 0; i < OTP_RCE_SIGN_SZ; i++) {
1768 /* If any timeout happened, invalidate the subsequent bits with 0 */
1769 if (hndotp_write_bit(oh, cc, bit, (sign & (err ? 0 : 1)), err)) {
1770 OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row"
1771 " number bit %x\n", __FUNCTION__, r, rce, i));
1772 err++;
1774 sign >>= 1;
1775 bit ++;
1778 if (err) {
1779 OTP_ERR(("%s: row %d not fixed by RCE %d due to %d timeouts. try next"
1780 " RCE\n", __FUNCTION__, r, rce, err));
1781 continue;
1782 } else {
1783 OTP_MSG(("%s: Fixed row %d by RCE %d\n", __FUNCTION__, r, rce));
1784 return BCME_OK;
1788 OTP_ERR(("All RCE's are in use. Failed fixing OTP.\n"));
1789 /* Fatal error, unfixable. MFGC will have to fail. Board needs to be discarded!! */
1790 return BCME_NORESOURCE;
1793 /* Write a row and fix it with RCE if any error detected */
1794 static int
1795 hndotp_write_row(void *oh, chipcregs_t *cc, int wn, uint16* data, bool rewrite)
1797 otpinfo_t *oi = (otpinfo_t *)oh;
1798 int err = 0, i;
1800 ASSERT(wn % OTP_WPR == 0);
1802 /* Write the data */
1803 for (i = 0; i < OTP_WPR; i++) {
1804 if (rewrite && (data[i] == hndotp_otpr(oh, cc, wn+i)))
1805 continue;
1807 err += hndotp_write_word(oh, cc, wn + i, data[i]);
1810 /* Fix this row if any error */
1811 if (err && (oi->ccrev >= 18)) {
1812 OTP_DBG(("%s: %d write errors in row %d. Fixing...\n", __FUNCTION__, err, wn/4));
1813 if ((err = hndotp_write_rce(oh, cc, wn / OTP_WPR, data)))
1814 OTP_MSG(("%s: failed to fix row %d\n", __FUNCTION__, wn/4));
1817 return err;
1820 /* expects the caller to disable interrupts before calling this routine */
1821 static int
1822 hndotp_write_region(void *oh, int region, uint16 *data, uint wlen)
1824 otpinfo_t *oi = (otpinfo_t *)oh;
1825 uint32 st;
1826 uint wn, base = 0, lim;
1827 int ret = BCME_OK;
1828 uint idx;
1829 chipcregs_t *cc;
1830 bool rewrite = FALSE;
1831 uint32 save_clk;
1833 ASSERT(wlen % OTP_WPR == 0);
1835 idx = si_coreidx(oi->sih);
1836 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1837 ASSERT(cc != NULL);
1839 /* Check valid region */
1840 if ((region != OTP_HW_REGION) &&
1841 (region != OTP_SW_REGION) &&
1842 (region != OTP_CID_REGION)) {
1843 ret = BCME_BADARG;
1844 goto out;
1847 /* Region already written? */
1848 st = oi->hwprot | oi-> signvalid;
1849 if ((st & region) != 0)
1850 rewrite = TRUE;
1852 /* HW and CID have to be written before SW */
1853 if ((((st & (OTP_HW_REGION | OTP_CID_REGION)) == 0) &&
1854 (st & OTP_SW_REGION) != 0)) {
1855 OTP_ERR(("%s: HW/CID region should be programmed first\n", __FUNCTION__));
1856 ret = BCME_BADARG;
1857 goto out;
1860 /* Bounds for the region */
1861 lim = (oi->size / 2) + OTP_SWLIM_OFF;
1862 if (region == OTP_HW_REGION) {
1863 base = 0;
1864 } else if (region == OTP_SW_REGION) {
1865 base = oi->boundary / 2;
1866 } else if (region == OTP_CID_REGION) {
1867 base = (oi->size / 2) + OTP_CID_OFF;
1868 lim = (oi->size / 2) + OTP_LIM_OFF;
1871 if (wlen > (lim - base)) {
1872 ret = BCME_BUFTOOLONG;
1873 goto out;
1875 lim = base + wlen;
1877 #if defined(WLTEST)
1878 st_n = st_s = st_hwm = pp_hwm = 0;
1879 #endif
1881 /* force ALP for progrramming stability */
1882 save_clk = R_REG(oi->osh, &cc->clk_ctl_st);
1883 OR_REG(oi->osh, &cc->clk_ctl_st, CCS_FORCEALP);
1884 OSL_DELAY(10);
1886 /* Write the data row by row */
1887 for (wn = base; wn < lim; wn += OTP_WPR, data += OTP_WPR) {
1888 if ((ret = hndotp_write_row(oh, cc, wn, data, rewrite)) != 0) {
1889 if (ret == BCME_NORESOURCE) {
1890 OTP_ERR(("%s: Abort at word %x\n", __FUNCTION__, wn));
1891 break;
1896 /* Don't need to update signature & boundary if rewrite */
1897 if (rewrite)
1898 goto out_rclk;
1900 /* Done with the data, write the signature & boundary if needed */
1901 if (region == OTP_HW_REGION) {
1902 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF, lim * 2) != 0) {
1903 ret = BCME_NORESOURCE;
1904 goto out_rclk;
1906 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF,
1907 OTP_SIGNATURE) != 0) {
1908 ret = BCME_NORESOURCE;
1909 goto out_rclk;
1911 oi->boundary = lim * 2;
1912 oi->signvalid |= OTP_HW_REGION;
1913 } else if (region == OTP_SW_REGION) {
1914 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_SWSIGN_OFF,
1915 OTP_SIGNATURE) != 0) {
1916 ret = BCME_NORESOURCE;
1917 goto out_rclk;
1919 oi->signvalid |= OTP_SW_REGION;
1920 } else if (region == OTP_CID_REGION) {
1921 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_CIDSIGN_OFF,
1922 OTP_SIGNATURE) != 0) {
1923 ret = BCME_NORESOURCE;
1924 goto out_rclk;
1926 oi->signvalid |= OTP_CID_REGION;
1929 out_rclk:
1930 /* Restore clock */
1931 W_REG(oi->osh, &cc->clk_ctl_st, save_clk);
1933 out:
1934 #if defined(WLTEST)
1935 OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n",
1936 st_n, st_s, st_n, st_n?(st_s / st_n):0, st_hwm, pp_hwm));
1937 #endif
1939 si_setcoreidx(oi->sih, idx);
1941 return ret;
1944 /* For HND OTP, there's no space for appending after filling in SROM image */
1945 static int
1946 hndotp_cis_append_region(si_t *sih, int region, char *vars, int count)
1948 return otp_write_region(sih, region, (uint16*)vars, count/2);
1951 /* Fill all unwritten RCE signature with 0 and return the number of them */
1952 static int
1953 hndotp_lock(void *oh)
1955 otpinfo_t *oi = (otpinfo_t *)oh;
1956 int i, j, e, rcr, bit, ret = 0;
1957 uint32 st, idx;
1958 chipcregs_t *cc;
1960 ASSERT(oi->ccrev >= 18);
1962 idx = si_coreidx(oi->sih);
1963 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
1964 ASSERT(cc != NULL);
1966 /* Region already written? */
1967 st = oi->hwprot | oi-> signvalid;
1968 if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == 0) {
1969 si_setcoreidx(oi->sih, idx);
1970 return BCME_NOTREADY; /* Don't lock unprogrammed OTP */
1973 /* Find the highest valid RCE */
1974 for (i = 0; i < OTP_RCE_ROW_SZ -1; i++) {
1975 if ((hndotp_valid_rce(oh, cc, i) != -1))
1976 break;
1978 i--; /* Start invalidating from the next RCE */
1980 for (; i >= 0; i--) {
1981 if ((hndotp_valid_rce(oh, cc, i) == -1)) {
1983 ret++; /* This is a unprogrammed row */
1985 /* Invalidate the row with 0 */
1986 if (i < 3) {
1987 e = i;
1988 rcr = hndotp_size(oh)/2 + OTP_RC0_OFF;
1989 } else {
1990 e = i - 3;
1991 rcr = hndotp_size(oh)/2 + OTP_RC1_OFF;
1994 /* Fill row numer and signature with 0 bit-by-bit */
1995 bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0;
1996 for (j = 0; j < (OTP_RCE_ROW_SZ + OTP_RCE_SIGN_SZ); j++) {
1997 hndotp_write_bit(oh, cc, bit, 0, 1);
1998 bit ++;
2001 OTP_MSG(("locking rce %d\n", i));
2005 si_setcoreidx(oi->sih, idx);
2007 return ret;
2010 /* expects the caller to disable interrupts before calling this routine */
2011 static int
2012 hndotp_nvwrite(void *oh, uint16 *data, uint wlen)
2014 otpinfo_t *oi = (otpinfo_t *)oh;
2015 uint32 st;
2016 uint16 crc, clen, *p, hdr[2];
2017 uint wn, base = 0, lim;
2018 int err, gerr = 0;
2019 uint idx;
2020 chipcregs_t *cc;
2022 /* otp already written? */
2023 st = oi->hwprot | oi-> signvalid;
2024 if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == (OTP_HW_REGION | OTP_SW_REGION))
2025 return BCME_EPERM;
2027 /* save the orig core */
2028 idx = si_coreidx(oi->sih);
2029 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2030 ASSERT(cc != NULL);
2032 /* Bounds for the region */
2033 lim = (oi->size / 2) + OTP_SWLIM_OFF;
2034 base = 0;
2036 /* Look for possible chunks from the end down */
2037 wn = lim;
2038 while (wn > 0) {
2039 wn--;
2040 if (hndotp_otpr(oh, cc, wn) == OTP_MAGIC) {
2041 base = wn + (hndotp_otpr(oh, cc, wn + 1) / 2);
2042 break;
2045 if (base == 0) {
2046 OTP_MSG(("Unprogrammed otp\n"));
2047 } else {
2048 OTP_MSG(("Found some chunks, skipping to 0x%x\n", base * 2));
2050 if ((wlen + 3) > (lim - base)) {
2051 err = BCME_NORESOURCE;
2052 goto out;
2055 #if defined(WLTEST)
2056 st_n = st_s = st_hwm = pp_hwm = 0;
2057 #endif
2059 /* Prepare the header and crc */
2060 hdr[0] = OTP_MAGIC;
2061 hdr[1] = (wlen + 3) * 2;
2062 crc = hndcrc16((uint8 *)hdr, sizeof(hdr), CRC16_INIT_VALUE);
2063 crc = hndcrc16((uint8 *)data, wlen * 2, crc);
2064 crc = ~crc;
2066 do {
2067 p = data;
2068 wn = base + 2;
2069 lim = base + wlen + 2;
2071 OTP_MSG(("writing chunk, 0x%x bytes @ 0x%x-0x%x\n", wlen * 2,
2072 base * 2, (lim + 1) * 2));
2074 /* Write the header */
2075 err = hndotp_write_word(oh, cc, base, hdr[0]);
2077 /* Write the data */
2078 while (wn < lim) {
2079 err += hndotp_write_word(oh, cc, wn++, *p++);
2081 /* If there has been an error, close this chunk */
2082 if (err != 0) {
2083 OTP_MSG(("closing early @ 0x%x\n", wn * 2));
2084 break;
2088 /* If we wrote the whole chunk, write the crc */
2089 if (wn == lim) {
2090 OTP_MSG((" whole chunk written, crc = 0x%x\n", crc));
2091 err += hndotp_write_word(oh, cc, wn++, crc);
2092 clen = hdr[1];
2093 } else {
2094 /* If there was an error adjust the count to point to
2095 * the word after the error so we can start the next
2096 * chunk there.
2098 clen = (wn - base) * 2;
2099 OTP_MSG((" partial chunk written, chunk len = 0x%x\n", clen));
2101 /* And now write the chunk length */
2102 err += hndotp_write_word(oh, cc, base + 1, clen);
2104 if (base == 0) {
2105 /* Write the signature and boundary if this is the HW region,
2106 * but don't report failure if either of these 2 writes fail.
2108 if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF,
2109 wn * 2) == 0)
2110 gerr += hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF,
2111 OTP_SIGNATURE);
2112 else
2113 gerr++;
2114 oi->boundary = wn * 2;
2115 oi->signvalid |= OTP_HW_REGION;
2118 if (err != 0) {
2119 gerr += err;
2120 /* Errors, do it all over again if there is space left */
2121 if ((wlen + 3) <= ((oi->size / 2) + OTP_SWLIM_OFF - wn)) {
2122 base = wn;
2123 lim = base + wlen + 2;
2124 OTP_ERR(("Programming errors, retry @ 0x%x\n", wn * 2));
2125 } else {
2126 OTP_ERR(("Programming errors, no space left ( 0x%x)\n", wn * 2));
2127 break;
2130 } while (err != 0);
2132 OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n",
2133 st_n, st_s, st_n, st_s / st_n, st_hwm, pp_hwm));
2135 if (gerr != 0)
2136 OTP_MSG(("programming %s after %d errors\n", (err == 0) ? "succedded" : "failed",
2137 gerr));
2138 out:
2139 /* done */
2140 si_setcoreidx(oi->sih, idx);
2142 if (err)
2143 return BCME_ERROR;
2144 else
2145 return 0;
2147 #endif /* BCMNVRAMW */
2149 #if defined(WLTEST)
2150 static uint16
2151 hndotp_otprb16(void *oh, chipcregs_t *cc, uint wn)
2153 uint base, i;
2154 uint16 val, bit;
2156 base = (wn * 16) + (wn / 4);
2157 val = 0;
2158 for (i = 0; i < 16; i++) {
2159 if ((bit = hndotp_read_bit(oh, cc, base + i)) == 0xffff)
2160 break;
2161 val = val | (bit << i);
2163 if (i < 16)
2164 val = 0xaaaa;
2165 return val;
2168 static int
2169 hndotp_dump(void *oh, int arg, char *buf, uint size)
2171 otpinfo_t *oi = (otpinfo_t *)oh;
2172 chipcregs_t *cc;
2173 uint idx, i, count, lil;
2174 uint16 val;
2175 struct bcmstrbuf b;
2177 idx = si_coreidx(oi->sih);
2178 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2179 ASSERT(cc != NULL);
2181 if (arg >= 16)
2182 arg -= 16;
2184 if (arg == 2) {
2185 count = 66 * 4;
2186 lil = 3;
2187 } else {
2188 count = (oi->size / 2) + OTP_RC_LIM_OFF;
2189 lil = 7;
2192 OTP_MSG(("%s: arg %d, size %d, words %d\n", __FUNCTION__, arg, size, count));
2193 bcm_binit(&b, buf, size);
2194 for (i = 0; i < count; i++) {
2195 if ((i & lil) == 0)
2196 bcm_bprintf(&b, "0x%04x:", 2 * i);
2198 if (arg == 0)
2199 val = hndotp_otpr(oh, cc, i);
2200 else
2201 val = hndotp_otprb16(oi, cc, i);
2202 bcm_bprintf(&b, " 0x%04x", val);
2203 if ((i & lil) == lil) {
2204 if (arg == 2) {
2205 bcm_bprintf(&b, " %d\n",
2206 hndotp_read_bit(oh, cc, ((i / 4) * 65) + 64) & 1);
2207 } else {
2208 bcm_bprintf(&b, "\n");
2212 if ((i & lil) != lil)
2213 bcm_bprintf(&b, "\n");
2215 OTP_MSG(("%s: returning %d, left %d, wn %d\n",
2216 __FUNCTION__, (int)(b.buf - b.origbuf), b.size, i));
2218 si_setcoreidx(oi->sih, idx);
2220 return ((int)(b.buf - b.origbuf));
2222 #endif
2224 static otp_fn_t hndotp_fn = {
2225 (otp_status_t)hndotp_status,
2226 (otp_size_t)hndotp_size,
2227 (otp_read_bit_t)hndotp_read_bit,
2228 (otp_init_t)hndotp_init,
2229 (otp_read_region_t)hndotp_read_region,
2230 (otp_nvread_t)hndotp_nvread,
2231 #ifdef BCMNVRAMW
2232 (otp_write_region_t)hndotp_write_region,
2233 (otp_cis_append_region_t)hndotp_cis_append_region,
2234 (otp_lock_t)hndotp_lock,
2235 (otp_nvwrite_t)hndotp_nvwrite,
2236 #endif /* BCMNVRAMW */
2237 #if defined(WLTEST)
2238 (otp_dump_t)hndotp_dump,
2239 #endif
2240 OTP_FN_MAGIC
2243 #endif /* BCMAUTOOTP || BCMHNDOTP */
2247 * Common Code: Compiled for IPX / HND / AUTO
2248 * otp_status()
2249 * otp_size()
2250 * otp_read_bit()
2251 * otp_init()
2252 * otp_read_region()
2253 * otp_nvread()
2254 * otp_write_region()
2255 * otp_cis_append_region()
2256 * otp_lock()
2257 * otp_nvwrite()
2258 * otp_dump()
2259 * otp_dumpstats()
2263 otp_status(void *oh)
2265 otpinfo_t *oi = (otpinfo_t *)oh;
2267 return oi->fn->status(oh);
2271 otp_size(void *oh)
2273 otpinfo_t *oi = (otpinfo_t *)oh;
2275 return oi->fn->size(oh);
2278 uint16
2279 otp_read_bit(void *oh, uint offset)
2281 otpinfo_t *oi = (otpinfo_t *)oh;
2282 uint idx = si_coreidx(oi->sih);
2283 chipcregs_t *cc = si_setcoreidx(oi->sih, SI_CC_IDX);
2284 uint16 readBit = (uint16)oi->fn->read_bit(oh, cc, offset);
2285 si_setcoreidx(oi->sih, idx);
2286 return readBit;
2289 void *
2290 BCMNMIATTACHFN(otp_init)(si_t *sih)
2292 otpinfo_t *oi;
2293 void *ret = NULL;
2295 oi = &otpinfo;
2296 bzero(oi, sizeof(otpinfo_t));
2298 oi->ccrev = sih->ccrev;
2300 #if defined(BCMAUTOOTP)
2301 OTP_MSG(("%s: Compiled for AUTO OTP\n", __FUNCTION__));
2302 /* Auto-select based on chipc rev */
2303 if (oi->ccrev < 21 || oi->ccrev == 22) { /* HND OTP */
2304 oi->fn = &hndotp_fn;
2305 } else { /* IPX OTP */
2306 oi->fn = &ipxotp_fn;
2308 #else /* BCMAUTOOTP - no auto-selection */
2309 #if !defined(BCMHNDOTP) /* Newer IPX OTP wrapper */
2310 OTP_MSG(("%s: Compiled for IPX OTP\n", __FUNCTION__));
2311 oi->fn = &ipxotp_fn;
2312 #else /* !BCMHNDOTP - Older HND OTP controller */
2313 OTP_MSG(("%s: Compiled for HND OTP\n", __FUNCTION__));
2314 oi->fn = &hndotp_fn;
2315 #endif
2316 #endif /* BCMAUTOOTP */
2317 ASSERT(oi->fn->magic == OTP_FN_MAGIC);
2319 oi->sih = sih;
2320 oi->osh = si_osh(oi->sih);
2322 ret = (oi->fn->init)(sih);
2324 return ret;
2328 BCMNMIATTACHFN(otp_read_region)(si_t *sih, int region, uint16 *data, uint *wlen)
2330 bool wasup = FALSE;
2331 void *oh;
2332 int err = 0;
2334 if (!(wasup = si_is_otp_powered(sih)))
2335 si_otp_power(sih, TRUE);
2337 if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2338 err = BCME_NOTREADY;
2339 goto out;
2342 oh = otp_init(sih);
2343 if (oh == NULL) {
2344 OTP_ERR(("otp_init failed.\n"));
2345 err = BCME_ERROR;
2346 goto out;
2349 err = (((otpinfo_t*)oh)->fn->read_region)(oh, region, data, wlen);
2351 out:
2352 if (!wasup)
2353 si_otp_power(sih, FALSE);
2355 return err;
2359 otp_nvread(void *oh, char *data, uint *len)
2361 otpinfo_t *oi = (otpinfo_t *)oh;
2363 return oi->fn->nvread(oh, data, len);
2366 #ifdef BCMNVRAMW
2368 BCMNMIATTACHFN(otp_write_region)(si_t *sih, int region, uint16 *data, uint wlen)
2370 bool wasup = FALSE;
2371 void *oh;
2372 int err = 0;
2374 if (!(wasup = si_is_otp_powered(sih)))
2375 si_otp_power(sih, TRUE);
2377 if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2378 err = BCME_NOTREADY;
2379 goto out;
2382 oh = otp_init(sih);
2383 if (oh == NULL) {
2384 OTP_ERR(("otp_init failed.\n"));
2385 err = BCME_ERROR;
2386 goto out;
2389 err = (((otpinfo_t*)oh)->fn->write_region)(oh, region, data, wlen);
2391 out:
2392 if (!wasup)
2393 si_otp_power(sih, FALSE);
2395 return err;
2399 otp_cis_append_region(si_t *sih, int region, char *vars, int count)
2401 void *oh = otp_init(sih);
2403 return (((otpinfo_t*)oh)->fn->cis_append_region)(sih, region, vars, count);
2407 otp_lock(si_t *sih)
2409 bool wasup = FALSE;
2410 void *oh;
2411 int ret = 0;
2413 if (!(wasup = si_is_otp_powered(sih)))
2414 si_otp_power(sih, TRUE);
2416 if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
2417 ret = BCME_NOTREADY;
2418 goto out;
2421 oh = otp_init(sih);
2422 if (oh == NULL) {
2423 OTP_ERR(("otp_init failed.\n"));
2424 ret = BCME_ERROR;
2425 goto out;
2428 ret = (((otpinfo_t*)oh)->fn->lock)(oh);
2430 out:
2431 if (!wasup)
2432 si_otp_power(sih, FALSE);
2434 return ret;
2438 otp_nvwrite(void *oh, uint16 *data, uint wlen)
2440 otpinfo_t *oi = (otpinfo_t *)oh;
2442 return oi->fn->nvwrite(oh, data, wlen);
2444 #endif /* BCMNVRAMW */
2446 #if defined(WLTEST)
2448 otp_dump(void *oh, int arg, char *buf, uint size)
2450 otpinfo_t *oi = (otpinfo_t *)oh;
2452 return oi->fn->dump(oh, arg, buf, size);
2456 otp_dumpstats(void *oh, int arg, char *buf, uint size)
2458 otpinfo_t *oi = (otpinfo_t *)oh;
2459 struct bcmstrbuf b;
2461 bcm_binit(&b, buf, size);
2463 bcm_bprintf(&b, "\nOTP, ccrev 0x%04x\n", oi->ccrev);
2464 #if defined(BCMAUTOOTP) || !defined(BCMHNDOTP) /* Newer IPX OTP wrapper */
2465 bcm_bprintf(&b, "wsize %d rows %d cols %d\n", oi->wsize, oi->rows, oi->cols);
2466 bcm_bprintf(&b, "hwbase %d hwlim %d swbase %d swlim %d\n", oi->hwbase, oi->hwlim,
2467 oi->swbase, oi->swlim, oi->fbase, oi->flim);
2468 bcm_bprintf(&b, "otpgu_base %d status %d\n", oi->otpgu_base, oi->status);
2469 #endif
2470 #if defined(BCMAUTOOTP) || defined(BCMHNDOTP) /* Older HND OTP wrapper */
2471 bcm_bprintf(&b, "OLD OTP, size %d hwprot 0x%x signvalid 0x%x boundary %d\n",
2472 oi->size, oi->hwprot, oi->signvalid, oi->boundary);
2473 #endif
2474 bcm_bprintf(&b, "\n");
2476 return 200; /* real buf length, pick one to cover above print */
2479 #endif