4 * Copyright (C) 2009, Broadcom Corporation
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 $
21 #include <bcmendian.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
;
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. */
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
{
64 otp_read_bit_t read_bit
;
66 otp_read_region_t read_region
;
69 otp_write_region_t write_region
;
70 otp_cis_append_region_t cis_append_region
;
72 otp_nvwrite_t nvwrite
;
73 #endif /* BCMNVRAMW */
79 #define OTP_FN_MAGIC 0x87654321
82 uint ccrev
; /* chipc revision */
83 otp_fn_t
*fn
; /* OTP functions */
84 si_t
*sih
; /* Saved sb handle */
86 #if defined(BCMAUTOOTP) || !defined(BCMHNDOTP) /* Newer IPX OTP wrapper */
88 uint16 wsize
; /* Size of otp in words */
91 /* Flag bits (lock/prog/rv). Reflected only when OTP is power cycled */
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 */
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 */
120 static otpinfo_t otpinfo
;
124 * IPX OTP Code: Compiled for IPX OTP or AUTO mode
125 * Exported functions:
130 * ipxotp_read_region()
132 * ipxotp_write_region()
133 * ipxotp_cis_append_region()
138 * IPX internal functions:
144 * ipxotp_fix_word16()
145 * ipxotp_check_word16()
151 #if defined(BCMAUTOOTP) || !defined(BCMHNDOTP) /* Newer IPX OTP wrapper */
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)
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 */
183 ipxotp_status(void *oh
)
185 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
186 return (int)(oi
->status
);
189 /* Return size in bytes */
191 ipxotp_size(void *oh
)
193 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
194 return (int)oi
->wsize
* 2;
198 ipxotp_otpr(void *oh
, chipcregs_t
*cc
, uint wn
)
202 oi
= (otpinfo_t
*)oh
;
204 ASSERT(wn
< oi
->wsize
);
207 return R_REG(oi
->osh
, &cc
->sromotp
[wn
]);
211 ipxotp_read_bit(void *oh
, chipcregs_t
*cc
, uint off
)
213 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
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
);
229 ((st
= R_REG(oi
->osh
, &cc
->otpprog
)) & OTPP_START_BUSY
) && (k
< OTPP_TRIES
);
232 if (k
>= OTPP_TRIES
) {
233 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__
, st
, k
));
236 if (st
& OTPP_READERR
) {
237 OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__
, off
));
240 st
= (st
& OTPP_VALUE_MASK
) >> OTPP_VALUE_SHIFT
;
242 OTP_DBG((" => %d\n", 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
251 ipxotp_max_rgnsz(si_t
*sih
, int osizew
)
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
;
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
;
271 case BCM4319_CHIP_ID
:
275 ASSERT(0); /* Don't konw about this chip */
278 OTP_MSG(("max region size %d bytes\n", ret
));
283 BCMNMIATTACHFN(_ipxotp_init
)(otpinfo_t
*oi
, chipcregs_t
*cc
)
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
;
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
);
303 ((st
= R_REG(oi
->osh
, &cc
->otpprog
)) & OTPP_START_BUSY
) && (k
< OTPP_TRIES
);
306 if (k
>= OTPP_TRIES
) {
307 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__
, st
, k
));
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
) ||
322 p_bits
= (ipxotp_otpr(oi
, cc
, oi
->otpgu_base
+ OTPGU_P_OFF
) & OTPGU_P_MSK
)
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
;
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
;
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));
361 BCMNMIATTACHFN(ipxotp_init
)(si_t
*sih
)
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)
374 /* Make sure OTP is not disabled */
375 if (si_is_otp_disabled(sih
)) {
376 OTP_MSG(("%s: OTP is disabled\n", __FUNCTION__
));
382 /* Make sure OTP is powered up */
383 if (!si_is_otp_powered(sih
)) {
384 OTP_ERR(("%s: OTP is powered down\n", __FUNCTION__
));
390 /* Check for otp size */
391 switch ((sih
->cccaps
& CC_CAP_OTPSIZE
) >> CC_CAP_OTPSIZE_SHIFT
) {
394 OTP_ERR(("%s: no OTP\n", __FUNCTION__
));
412 /* Don't know the geometry */
413 OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__
));
417 OTP_MSG(("%s: rows %u cols %u wsize %u\n", __FUNCTION__
, oi
->rows
, oi
->cols
, oi
->wsize
));
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;
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
);
453 _ipxotp_init(oi
, cc
);
455 si_setcoreidx(sih
, idx
);
461 ipxotp_read_region(void *oh
, int region
, uint16
*data
, uint
*wlen
)
463 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
468 /* Validate region selection */
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__
));
475 return BCME_NOTFOUND
;
478 OTP_ERR(("%s: buffer too small, should be at least %u\n",
479 __FUNCTION__
, oi
->hwlim
- oi
->hwbase
));
481 return BCME_BUFTOOSHORT
;
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__
));
490 return BCME_NOTFOUND
;
493 OTP_ERR(("%s: buffer too small should be at least %u\n",
494 __FUNCTION__
, oi
->swlim
- oi
->swbase
));
496 return BCME_BUFTOOSHORT
;
502 if (!(oi
->status
& OTPS_GUP_CI
)) {
503 OTP_ERR(("%s: chipid region not programmed\n", __FUNCTION__
));
505 return BCME_NOTFOUND
;
508 OTP_ERR(("%s: buffer too small, should be at least %u\n",
509 __FUNCTION__
, OTPGU_CI_SZ
));
511 return BCME_BUFTOOSHORT
;
513 base
= oi
->otpgu_base
+ OTPGU_CI_OFF
;
516 sz
= (uint
)oi
->flim
- oi
->fbase
;
517 if (!(oi
->status
& OTPS_GUP_FUSE
)) {
518 OTP_ERR(("%s: fuse region not programmed\n", __FUNCTION__
));
520 return BCME_NOTFOUND
;
523 OTP_ERR(("%s: buffer too small, should be at least %u\n",
524 __FUNCTION__
, oi
->flim
- oi
->fbase
));
526 return BCME_BUFTOOSHORT
;
531 OTP_ERR(("%s: reading region %d is not supported\n", __FUNCTION__
, region
));
535 idx
= si_coreidx(oi
->sih
);
536 cc
= si_setcoreidx(oi
->sih
, SI_CC_IDX
);
540 for (i
= 0; i
< sz
; i
++)
541 data
[i
] = ipxotp_otpr(oh
, cc
, base
+ i
);
543 si_setcoreidx(oi
->sih
, idx
);
549 ipxotp_nvread(void *oh
, char *data
, uint
*len
)
551 return BCME_UNSUPPORTED
;
556 ipxotp_write_bit(otpinfo_t
*oi
, chipcregs_t
*cc
, uint off
)
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
);
574 ((st
= R_REG(oi
->osh
, &cc
->otpprog
)) & OTPP_START_BUSY
) && (k
< OTPP_TRIES
);
577 if (k
>= OTPP_TRIES
) {
578 OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__
, st
, k
));
586 ipxotp_otpwb16(otpinfo_t
*oi
, chipcregs_t
*cc
, int wn
, uint16 data
)
592 for (i
= 0; i
< 16; i
++) {
593 if (data
& (1 << i
)) {
594 if ((rc
= ipxotp_write_bit(oi
, cc
, base
+ i
)))
602 /* Write OTP redundancy entry:
603 * rde - redundancy entry index (-ve for "next")
608 ipxotp_write_rde(void *oh
, int rde
, uint bit
, uint val
)
610 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
616 if ((rde
>= oi
->rde_cb
.offsets
) || (bit
>= oi
->rows
* oi
->cols
) || (val
> 1))
621 for (rde
= 0; rde
< oi
->rde_cb
.offsets
- 1; rde
++) {
622 if ((oi
->status
& (1 << (oi
->rde_cb
.stat_shift
+ rde
))) == 0)
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__
,
634 idx
= si_coreidx(oi
->sih
);
635 cc
= si_setcoreidx(oi
->sih
, SI_CC_IDX
);
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
));
644 OR_REG(oi
->osh
, &cc
->otpcontrol
, OTPC_PROGEN
);
646 for (i
= 0; i
< oi
->rde_cb
.width
; i
++) {
647 if (!(temp
& (1 << i
)))
649 ipxotp_write_bit(oi
, cc
, oi
->rde_cb
.offset
[rde
] + i
);
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
);
663 /* Set up redundancy entries for the specified bits */
665 ipxotp_fix_word16(void *oh
, uint wn
, uint16 mask
, uint16 val
)
671 oi
= (otpinfo_t
*)oh
;
674 ASSERT(wn
< oi
->wsize
);
676 for (bit
= wn
* 16; mask
; bit
++, mask
>>= 1, val
>>= 1) {
678 if ((rc
= ipxotp_write_rde(oi
, -1, bit
, val
& 1)))
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
);
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
;
709 /* expects the caller to disable interrupts before calling this routine */
711 ipxotp_write_region(void *oh
, int region
, uint16
*data
, uint wlen
)
713 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
718 bool rewrite
= FALSE
;
720 uint16
*origdata
= NULL
;
722 otpgu_bit_base
= oi
->otpgu_base
* 16;
724 /* Validate region selection */
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
);
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
);
745 if (oi
->status
& OTPS_GUP_CI
) {
746 OTP_ERR(("%s: chipid region has been programmed\n", __FUNCTION__
));
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__
));
758 base
= oi
->otpgu_base
+ OTPGU_CI_OFF
;
761 if (oi
->status
& OTPS_GUP_FUSE
) {
762 OTP_ERR(("%s: fuse region has been programmed\n", __FUNCTION__
));
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
;
773 OTP_ERR(("%s: writing region %d is not supported\n", __FUNCTION__
, region
));
777 idx
= si_coreidx(oi
->sih
);
778 cc
= si_setcoreidx(oi
->sih
, SI_CC_IDX
);
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
) {
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
]));
797 data
[i
] ^= origdata
[i
];
799 OTP_MSG(("%s: writing new bits in %s region\n", __FUNCTION__
, HWSW_RGN(region
)));
802 OR_REG(oi
->osh
, &cc
->otpcontrol
, OTPC_PROGEN
);
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 */
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
);
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
);
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
828 if (wlen
>= OTPGU_CI_SZ
)
829 data
[OTPGU_CI_SZ
- 1] |= OTPGU_CIP_MSK
;
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
);
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 */
847 uint16 boundary_off
= 0, boundary_val
= 0;
848 uint16 programmed_off
= 0;
853 boundary_off
= OTPGU_HSB_OFF
;
854 boundary_val
= (base
+ i
) * 16;
855 programmed_off
= OTPGU_HWP_OFF
;
858 /* Also write 0 to HW region boundary */
859 if ((rc
= ipxotp_check_word16(oi
, cc
, oi
->otpgu_base
+ OTPGU_HSB_OFF
,
862 boundary_off
= OTPGU_SFB_OFF
;
863 boundary_val
= oi
->swlim
* 16;
864 programmed_off
= OTPGU_SWP_OFF
;
867 /* No CI region boundary */
868 programmed_off
= OTPGU_CIP_OFF
;
871 boundary_off
= OTPGU_SFB_OFF
;
872 boundary_val
= base
* 16;
873 programmed_off
= OTPGU_FUSEP_OFF
;
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
,
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
));
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",
899 /* Update status, apply WAR */
900 _ipxotp_init(oi
, cc
);
902 /* Recover original data... */
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
])))
914 MFREE(oi
->osh
, origdata
, wlen
* 2);
916 si_setcoreidx(oi
->sih
, idx
);
921 ipxotp_cis_append_region(si_t
*sih
, int region
, char *vars
, int count
)
925 uint sz
= OTP_SZ_MAX
/2; /* size in words */
927 bool newchip
= FALSE
;
929 ASSERT(region
== OTP_HW_RGN
|| region
== OTP_SW_RGN
);
932 if ((cis
= MALLOC(osh
, OTP_SZ_MAX
)) == NULL
) {
936 bzero(cis
, OTP_SZ_MAX
);
938 rc
= otp_read_region(sih
, region
, (uint16
*)cis
, &sz
);
939 newchip
= (rc
== BCME_NOTFOUND
) ? TRUE
: FALSE
;
942 /* zero count for read, non-zero count for write */
944 int i
= 0, newlen
= 0;
947 int termw_len
= 0; /* length of termination word */
949 /* convert halfwords to bytes offset */
952 if ((CHIPID(sih
->chip
) == BCM4322_CHIP_ID
) ||
953 (CHIPID(sih
->chip
) == BCM43231_CHIP_ID
) ||
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;
965 cis
[newlen
-1] = 0xff;
966 cis
[newlen
-2] = 0xff;
970 if (count
>= newlen
- termw_len
) {
971 OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", newlen
, count
));
972 rc
= BCME_BUFTOOLONG
;
977 /* Walk through the leading zeros (could be 0 or 8 bytes for now) */
978 for (i
= 0; i
< (int)sz
*2; i
++)
982 /* Find the place to append */
983 for (; i
< (int)sz
*2; i
++) {
986 i
+= ((int)cis
[i
+1] + 1);
989 for (end
= i
; end
< (int)sz
*2; end
++) {
995 if (newlen
& 1) /* make it even-sized buffer */
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
);
1007 /* Write the buffer back */
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) {
1020 #endif /* BCMNVRAMW */
1024 MFREE(osh
, cis
, OTP_SZ_MAX
);
1029 /* No need to lock for IPXOTP. HNDOTP needs it due to the randomness of unprogrammed
1033 ipxotp_lock(void *oh
)
1039 ipxotp_nvwrite(void *oh
, uint16
*data
, uint wlen
)
1043 #endif /* BCMNVRAMW */
1047 ipxotp_otprb16(void *oh
, chipcregs_t
*cc
, uint wn
)
1056 for (i
= 0; i
< 16; i
++) {
1057 if ((bit
= ipxotp_read_bit(oh
, cc
, base
+ i
)) == 0xffff)
1059 val
= val
| (bit
<< i
);
1068 ipxotp_dump(void *oh
, int arg
, char *buf
, uint size
)
1070 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1076 idx
= si_coreidx(oi
->sih
);
1077 cc
= si_setcoreidx(oi
->sih
, SI_CC_IDX
);
1080 count
= ipxotp_size(oh
);
1082 bcm_binit(&b
, buf
, size
);
1083 for (i
= 0; i
< count
/ 2; i
++) {
1085 bcm_bprintf(&b
, "\n0x%04x:", 2 * i
);
1087 val
= ipxotp_otpr(oh
, cc
, i
);
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
));
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
,
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 */
1114 (otp_dump_t
)ipxotp_dump
,
1119 #endif /* BCMAUTOOTP || !BCMHNDOTP */
1123 * HND OTP Code: Compiled for HND OTP or AUTO mode
1124 * Exported functions:
1129 * hndotp_read_region()
1131 * hndotp_write_region()
1132 * hndotp_cis_append_region()
1137 * HND internal functions:
1140 * hndotp_write_bit()
1141 * hndotp_write_word()
1142 * hndotp_valid_rce()
1143 * hndotp_write_rce()
1144 * hndotp_write_row()
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"
1195 #if OTP_SW_REGION != OTP_SW_RGN
1196 #error "incompatible OTP_SW_RGN"
1198 #if OTP_CID_REGION != OTP_CI_RGN
1199 #error "incompatible OTP_CI_RGN"
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
1211 #define OTP_SIGNATURE 0x578a
1212 #define OTP_MAGIC 0x4e56
1215 hndotp_status(void *oh
)
1217 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1218 return ((int)(oi
->hwprot
| oi
->signvalid
));
1222 hndotp_size(void *oh
)
1224 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1225 return ((int)(oi
->size
));
1229 hndotp_otpr(void *oh
, chipcregs_t
*cc
, uint wn
)
1231 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1235 ASSERT(wn
< ((oi
->size
/ 2) + OTP_RC_LIM_OFF
));
1238 osh
= si_osh(oi
->sih
);
1240 ptr
= (uint16
*)((uchar
*)cc
+ CC_SROM_OTP
);
1241 return (R_REG(osh
, &ptr
[wn
]));
1245 hndotp_otproff(void *oh
, chipcregs_t
*cc
, int woff
)
1247 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1251 ASSERT(woff
>= (-((int)oi
->size
/ 2)));
1252 ASSERT(woff
< OTP_LIM_OFF
);
1255 osh
= si_osh(oi
->sih
);
1257 ptr
= (uint16
*)((uchar
*)cc
+ CC_SROM_OTP
);
1259 return (R_REG(osh
, &ptr
[(oi
->size
/ 2) + woff
]));
1263 hndotp_read_bit(void *oh
, chipcregs_t
*cc
, uint idx
)
1265 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1270 osh
= si_osh(oi
->sih
);
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
));
1290 if (st
& OTPP_READERR
) {
1291 OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__
, idx
));
1294 st
= (st
& OTPP_VALUE_MASK
) >> OTPP_VALUE_SHIFT
;
1295 OTP_DBG((" => %d\n", st
));
1300 BCMNMIATTACHFN(hndotp_init
)(si_t
*sih
)
1305 uint32 cap
= 0, clkdiv
, otpdiv
= 0;
1309 OTP_MSG(("%s: Use HND OTP controller\n", __FUNCTION__
));
1312 idx
= si_coreidx(sih
);
1313 osh
= si_osh(oi
->sih
);
1316 if ((cc
= si_setcoreidx(sih
, SI_CC_IDX
)) != NULL
) {
1317 cap
= R_REG(osh
, &cc
->capabilities
);
1318 if ((cap
& CC_CAP_OTPSIZE
) == 0) {
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)))
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
);
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)
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
));
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
,
1371 si_setcoreidx(sih
, idx
);
1377 hndotp_read_region(void *oh
, int region
, uint16
*data
, uint
*wlen
)
1379 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
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
));
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
);
1400 for (i
= 0; i
< (int)*wlen
; i
++)
1401 data
[i
] = hndotp_otpr(oh
, cc
, i
);
1403 si_setcoreidx(oi
->sih
, idx
);
1409 hndotp_nvread(void *oh
, char *data
, uint
*len
)
1412 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1413 uint32 base
, bound
, lim
= 0, st
;
1414 int i
, chunk
, gchunks
, tsz
= 0;
1418 uint16
*rawotp
= NULL
;
1420 /* save the orig core */
1421 idx
= si_coreidx(oi
->sih
);
1422 cc
= si_setcoreidx(oi
->sih
, SI_CC_IDX
);
1425 st
= hndotp_status(oh
);
1426 if (!(st
& (OTP_HW_REGION
| OTP_SW_REGION
))) {
1427 OTP_ERR(("OTP not programmed\n"));
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"));
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
)
1452 if (i
< (int)(lim
/ 2)) {
1454 bound
= (i
* 2) + rawotp
[i
+ 1];
1455 OTP_MSG(("otp: trying chunk at 0x%x-0x%x\n", i
* 2, bound
));
1457 OTP_MSG(("otp: unprogrammed\n"));
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
) {
1469 if (bound
!= rawotp
[1])
1470 OTP_MSG(("otp: Bound 0x%x != chunk0 len 0x%x\n", bound
,
1476 /* Find and copy the data */
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 */
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
));
1499 if (offset
+ dsz
>= *len
) {
1500 OTP_MSG(("Out of memory for otp\n"));
1503 bcopy((char *)&rawotp
[i
+ 2], &data
[offset
], dsz
);
1505 /* Remove extra null characters at the end */
1506 while (offset
> 1 &&
1507 data
[offset
- 1] == 0 && data
[offset
- 2] == 0)
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 */
1518 while (++i
< (int)(lim
/ 2))
1519 if (rawotp
[i
] == OTP_MAGIC
)
1522 if (i
< (int)(lim
/ 2))
1523 OTP_MSG(("trying next base 0x%x\n", i
* 2));
1525 OTP_MSG(("no more chunks\n"));
1530 OTP_MSG((" otp size = %d, boundary = 0x%x, nv base = 0x%x\n", lim
, bound
, base
));
1532 OTP_MSG((" Found %d bytes in %d good chunks out of %d\n", tsz
, gchunks
, chunk
));
1534 OTP_MSG((" No good chunks found out of %d\n", chunk
));
1541 MFREE(si_osh(oi
->sih
), rawotp
, lim
);
1542 si_setcoreidx(oi
->sih
, idx
);
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 */
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
;
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
));
1570 /* This is bit-at-a-time writing, future cores may do word-at-a-time */
1571 if (oi
->ccrev
== 12) {
1573 init_pwait
= 0x00000200;
1574 } else if (oi
->ccrev
== 22) {
1576 init_pwait
= 0x00000400;
1579 init_pwait
= 0x00004000;
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
);
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
);
1606 if (k
>= OTPP_TRIES
) {
1607 OTP_ERR(("BUSY stuck: pst=0x%x, count=%d\n", pst
, k
));
1611 st
= R_REG(osh
, &cc
->otpstatus
);
1612 if (((st
& OTPS_PROGFAIL
) == 0) || (pwait
== OTPC_PROGWAIT
) || (no_retry
)) {
1615 if ((oi
->ccrev
== 12) || (oi
->ccrev
== 22))
1616 pwait
= (pwait
<< 3) & OTPC_PROGWAIT
;
1618 pwait
= (pwait
<< 1) & OTPC_PROGWAIT
;
1620 pwait
= OTPC_PROGWAIT
;
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
));
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
));
1647 hndotp_write_word(void *oh
, chipcregs_t
*cc
, int wn
, uint16 data
)
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);
1660 /* abort write after first error to avoid stress the charge-pump */
1662 OTP_DBG(("%s: wn %d fail on bit %d\n", __FUNCTION__
, wn
, i
));
1671 hndotp_valid_rce(void *oh
, chipcregs_t
*cc
, int i
)
1673 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1675 uint32 hwv
, fw
, rce
, e
, sign
, row
, st
;
1677 ASSERT(oi
->ccrev
>= 18);
1680 osh
= si_osh(oi
->sih
);
1681 st
= R_REG(osh
, &cc
->otpstatus
);
1682 hwv
= (st
& OTPS_RCEV_MSK
) & (1 << (OTPS_RCEV_SHIFT
+ i
));
1686 fw
= hndotp_size(oh
)/2 + OTP_RC0_OFF
+ e
;
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;
1703 hndotp_write_rce(void *oh
, chipcregs_t
*cc
, int r
, uint16
* data
)
1708 ASSERT(((otpinfo_t
*)oh
)->ccrev
>= 18);
1709 ASSERT(r
>= 0 && r
< hndotp_size(oh
)/(2*OTP_WPR
));
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 */
1719 OTP_MSG(("%s: row %d already replaced by RCE %d",
1720 __FUNCTION__
, r
, rce
));
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
,
1737 OTP_MSG(("fail to write redundant row %d\n", rce
));
1742 /* Now write the redundant row index */
1745 rcr
= hndotp_size(oh
)/2 + OTP_RC0_OFF
;
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
;
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
));
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
));
1779 OTP_ERR(("%s: row %d not fixed by RCE %d due to %d timeouts. try next"
1780 " RCE\n", __FUNCTION__
, r
, rce
, err
));
1783 OTP_MSG(("%s: Fixed row %d by RCE %d\n", __FUNCTION__
, r
, rce
));
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 */
1795 hndotp_write_row(void *oh
, chipcregs_t
*cc
, int wn
, uint16
* data
, bool rewrite
)
1797 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
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
)))
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));
1820 /* expects the caller to disable interrupts before calling this routine */
1822 hndotp_write_region(void *oh
, int region
, uint16
*data
, uint wlen
)
1824 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1826 uint wn
, base
= 0, lim
;
1830 bool rewrite
= FALSE
;
1833 ASSERT(wlen
% OTP_WPR
== 0);
1835 idx
= si_coreidx(oi
->sih
);
1836 cc
= si_setcoreidx(oi
->sih
, SI_CC_IDX
);
1839 /* Check valid region */
1840 if ((region
!= OTP_HW_REGION
) &&
1841 (region
!= OTP_SW_REGION
) &&
1842 (region
!= OTP_CID_REGION
)) {
1847 /* Region already written? */
1848 st
= oi
->hwprot
| oi
-> signvalid
;
1849 if ((st
& region
) != 0)
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__
));
1860 /* Bounds for the region */
1861 lim
= (oi
->size
/ 2) + OTP_SWLIM_OFF
;
1862 if (region
== OTP_HW_REGION
) {
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
;
1878 st_n
= st_s
= st_hwm
= pp_hwm
= 0;
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
);
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
));
1896 /* Don't need to update signature & boundary if rewrite */
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
;
1906 if (hndotp_write_word(oh
, cc
, (oi
->size
/ 2) + OTP_HWSIGN_OFF
,
1907 OTP_SIGNATURE
) != 0) {
1908 ret
= BCME_NORESOURCE
;
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
;
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
;
1926 oi
->signvalid
|= OTP_CID_REGION
;
1931 W_REG(oi
->osh
, &cc
->clk_ctl_st
, save_clk
);
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
));
1939 si_setcoreidx(oi
->sih
, idx
);
1944 /* For HND OTP, there's no space for appending after filling in SROM image */
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 */
1953 hndotp_lock(void *oh
)
1955 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1956 int i
, j
, e
, rcr
, bit
, ret
= 0;
1960 ASSERT(oi
->ccrev
>= 18);
1962 idx
= si_coreidx(oi
->sih
);
1963 cc
= si_setcoreidx(oi
->sih
, SI_CC_IDX
);
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))
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 */
1988 rcr
= hndotp_size(oh
)/2 + OTP_RC0_OFF
;
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);
2001 OTP_MSG(("locking rce %d\n", i
));
2005 si_setcoreidx(oi
->sih
, idx
);
2010 /* expects the caller to disable interrupts before calling this routine */
2012 hndotp_nvwrite(void *oh
, uint16
*data
, uint wlen
)
2014 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
2016 uint16 crc
, clen
, *p
, hdr
[2];
2017 uint wn
, base
= 0, lim
;
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
))
2027 /* save the orig core */
2028 idx
= si_coreidx(oi
->sih
);
2029 cc
= si_setcoreidx(oi
->sih
, SI_CC_IDX
);
2032 /* Bounds for the region */
2033 lim
= (oi
->size
/ 2) + OTP_SWLIM_OFF
;
2036 /* Look for possible chunks from the end down */
2040 if (hndotp_otpr(oh
, cc
, wn
) == OTP_MAGIC
) {
2041 base
= wn
+ (hndotp_otpr(oh
, cc
, wn
+ 1) / 2);
2046 OTP_MSG(("Unprogrammed otp\n"));
2048 OTP_MSG(("Found some chunks, skipping to 0x%x\n", base
* 2));
2050 if ((wlen
+ 3) > (lim
- base
)) {
2051 err
= BCME_NORESOURCE
;
2056 st_n
= st_s
= st_hwm
= pp_hwm
= 0;
2059 /* Prepare the header and crc */
2061 hdr
[1] = (wlen
+ 3) * 2;
2062 crc
= hndcrc16((uint8
*)hdr
, sizeof(hdr
), CRC16_INIT_VALUE
);
2063 crc
= hndcrc16((uint8
*)data
, wlen
* 2, crc
);
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 */
2079 err
+= hndotp_write_word(oh
, cc
, wn
++, *p
++);
2081 /* If there has been an error, close this chunk */
2083 OTP_MSG(("closing early @ 0x%x\n", wn
* 2));
2088 /* If we wrote the whole chunk, write the crc */
2090 OTP_MSG((" whole chunk written, crc = 0x%x\n", crc
));
2091 err
+= hndotp_write_word(oh
, cc
, wn
++, crc
);
2094 /* If there was an error adjust the count to point to
2095 * the word after the error so we can start the next
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
);
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
,
2110 gerr
+= hndotp_write_word(oh
, cc
, (oi
->size
/ 2) + OTP_HWSIGN_OFF
,
2114 oi
->boundary
= wn
* 2;
2115 oi
->signvalid
|= OTP_HW_REGION
;
2120 /* Errors, do it all over again if there is space left */
2121 if ((wlen
+ 3) <= ((oi
->size
/ 2) + OTP_SWLIM_OFF
- wn
)) {
2123 lim
= base
+ wlen
+ 2;
2124 OTP_ERR(("Programming errors, retry @ 0x%x\n", wn
* 2));
2126 OTP_ERR(("Programming errors, no space left ( 0x%x)\n", wn
* 2));
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
));
2136 OTP_MSG(("programming %s after %d errors\n", (err
== 0) ? "succedded" : "failed",
2140 si_setcoreidx(oi
->sih
, idx
);
2147 #endif /* BCMNVRAMW */
2151 hndotp_otprb16(void *oh
, chipcregs_t
*cc
, uint wn
)
2156 base
= (wn
* 16) + (wn
/ 4);
2158 for (i
= 0; i
< 16; i
++) {
2159 if ((bit
= hndotp_read_bit(oh
, cc
, base
+ i
)) == 0xffff)
2161 val
= val
| (bit
<< i
);
2169 hndotp_dump(void *oh
, int arg
, char *buf
, uint size
)
2171 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
2173 uint idx
, i
, count
, lil
;
2177 idx
= si_coreidx(oi
->sih
);
2178 cc
= si_setcoreidx(oi
->sih
, SI_CC_IDX
);
2188 count
= (oi
->size
/ 2) + OTP_RC_LIM_OFF
;
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
++) {
2196 bcm_bprintf(&b
, "0x%04x:", 2 * i
);
2199 val
= hndotp_otpr(oh
, cc
, i
);
2201 val
= hndotp_otprb16(oi
, cc
, i
);
2202 bcm_bprintf(&b
, " 0x%04x", val
);
2203 if ((i
& lil
) == lil
) {
2205 bcm_bprintf(&b
, " %d\n",
2206 hndotp_read_bit(oh
, cc
, ((i
/ 4) * 65) + 64) & 1);
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
));
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
,
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 */
2238 (otp_dump_t
)hndotp_dump
,
2243 #endif /* BCMAUTOOTP || BCMHNDOTP */
2247 * Common Code: Compiled for IPX / HND / AUTO
2254 * otp_write_region()
2255 * otp_cis_append_region()
2263 otp_status(void *oh
)
2265 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
2267 return oi
->fn
->status(oh
);
2273 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
2275 return oi
->fn
->size(oh
);
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
);
2290 BCMNMIATTACHFN(otp_init
)(si_t
*sih
)
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
;
2316 #endif /* BCMAUTOOTP */
2317 ASSERT(oi
->fn
->magic
== OTP_FN_MAGIC
);
2320 oi
->osh
= si_osh(oi
->sih
);
2322 ret
= (oi
->fn
->init
)(sih
);
2328 BCMNMIATTACHFN(otp_read_region
)(si_t
*sih
, int region
, uint16
*data
, uint
*wlen
)
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
;
2344 OTP_ERR(("otp_init failed.\n"));
2349 err
= (((otpinfo_t
*)oh
)->fn
->read_region
)(oh
, region
, data
, wlen
);
2353 si_otp_power(sih
, FALSE
);
2359 otp_nvread(void *oh
, char *data
, uint
*len
)
2361 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
2363 return oi
->fn
->nvread(oh
, data
, len
);
2368 BCMNMIATTACHFN(otp_write_region
)(si_t
*sih
, int region
, uint16
*data
, uint wlen
)
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
;
2384 OTP_ERR(("otp_init failed.\n"));
2389 err
= (((otpinfo_t
*)oh
)->fn
->write_region
)(oh
, region
, data
, wlen
);
2393 si_otp_power(sih
, FALSE
);
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
);
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
;
2423 OTP_ERR(("otp_init failed.\n"));
2428 ret
= (((otpinfo_t
*)oh
)->fn
->lock
)(oh
);
2432 si_otp_power(sih
, FALSE
);
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 */
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
;
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
);
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
);
2474 bcm_bprintf(&b
, "\n");
2476 return 200; /* real buf length, pick one to cover above print */