2 * Write-once support for IPX OTP wrapper.
4 * Copyright 2007, 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.
21 #include <bcmendian.h>
30 #if !defined(CONFIG_BCMHNDOTP) /* Newer IPX OTP wrapper */
33 /* Subregion word offsets in General Use region */
34 #define OTPGU_HSB_OFF 12
35 #define OTPGU_SFB_OFF 13
36 #define OTPGU_CI_OFF 14
37 #define OTPGU_SROM_OFF 16
39 /* Fixed size subregions sizes in words */
42 /* Flag bit offsets in General Use region */
43 #define OTPGU_HWP_OFF 252
44 #define OTPGU_SWP_OFF 253
45 #define OTPGU_CIP_OFF 254
46 #define OTPGU_FUSEP_OFF 255
49 sb_t
*sbh
; /* Saved sb handle */
51 uint16 size
; /* Size of otp in words */
54 uint16 hwprot
; /* Hardware protection bits */
55 uint16 prog
; /* Subregion programmed bits */
56 uint16 hwbase
; /* hardware subregion offset */
57 uint16 hwlim
; /* hardware subregion boundary */
58 uint16 swbase
; /* software subregion offset */
59 uint16 swlim
; /* software subregion boundary */
60 uint16 fbase
; /* fuse subregion offset */
61 uint16 flim
; /* fuse subregion boundary */
64 static otpinfo_t otpinfo
;
66 #define OTPP_TRIES 10000000 /* # of tries for OTPP */
69 otp_rgn(otpinfo_t
*oi
, chipcregs_t
*cc
)
71 /* Read OTP lock bits and subregion programmed indication bits */
72 oi
->hwprot
= (uint16
)(R_REG(oi
->osh
, &cc
->otpstatus
) & OTPS_OL_MASK
);
73 oi
->prog
= (uint16
)(R_REG(oi
->osh
, &cc
->otpstatus
) & OTPS_GUP_MASK
);
74 OTP_MSG(("otp_rgn: hwprot %x prog %x\n", oi
->hwprot
, oi
->prog
));
77 * h/w region base and fuse region limit are fixed to the top and
78 * the bottom of the general use region. Everything else can be flexible.
80 oi
->hwbase
= OTPGU_SROM_OFF
;
82 if (oi
->prog
& OTPS_GUP_HW
) {
83 oi
->hwlim
= otpr(oi
, cc
, OTPGU_HSB_OFF
) / 16;
84 oi
->swbase
= oi
->hwlim
;
87 oi
->swbase
= oi
->hwbase
;
88 OTP_MSG(("otp_rgn: hwbase %x hwlim %x\n", oi
->hwbase
, oi
->hwlim
));
90 if (oi
->prog
& OTPS_GUP_SW
) {
91 oi
->swlim
= otpr(oi
, cc
, OTPGU_SFB_OFF
) / 16;
92 oi
->fbase
= oi
->swlim
;
95 oi
->fbase
= oi
->swbase
;
96 OTP_MSG(("otp_rgn: swbase %x swlim %x\n", oi
->swbase
, oi
->swlim
));
98 OTP_MSG(("otp_rgn: fbase %x flim %x\n", oi
->fbase
, oi
->flim
));
108 /* chipc corerev must be >= 21 */
113 bzero(oi
, sizeof(otpinfo_t
));
116 oi
->osh
= sb_osh(sbh
);
118 /* Check for otp size */
119 switch ((sbh
->cccaps
& CC_CAP_OTPSIZE
) >> CC_CAP_OTPSIZE_SHIFT
) {
122 OTP_MSG(("%s: no OTP\n", __FUNCTION__
));
128 OTP_MSG(("otp_init: rows %u cols %u\n", oi
->rows
, oi
->cols
));
131 /* Don't know the geometry */
132 OTP_MSG(("%s: unknown OTP geometry\n", __FUNCTION__
));
136 /* Retrieve OTP region info */
137 idx
= sb_coreidx(sbh
);
138 cc
= sb_setcore(sbh
, SB_CC
, 0);
142 #if defined(CONFIG_BCM4325)
143 case BCM4325_CHIP_ID
:
144 if ((sbh
->chipst
& CST4325_SPROM_OTP_SEL_MASK
) == CST4325_OTP_PWRDN
) {
145 OTP_MSG(("%s: OTP is strapped down\n", __FUNCTION__
));
149 if (!(R_REG(oi
->osh
, &cc
->min_res_mask
) & PMURES_BIT(RES4325_LNLDO2_PU
))) {
150 OTP_MSG(("%s: OTP is powered down\n", __FUNCTION__
));
164 sb_setcoreidx(sbh
, idx
);
170 otpr(void *oh
, chipcregs_t
*cc
, uint wn
)
174 oi
= (otpinfo_t
*)oh
;
176 ASSERT(wn
< oi
->size
);
179 return R_REG(oi
->osh
, &cc
->otp
[wn
]);
183 otp_read_region(void *oh
, int region
, uint16
*data
, uint wlen
)
185 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
190 /* Validate region selection */
193 if (!(oi
->prog
& OTPS_GUP_HW
)) {
194 OTP_MSG(("%s: h/w region not programmed\n", __FUNCTION__
));
197 if (wlen
< (sz
= (uint
)oi
->hwlim
- oi
->hwbase
)) {
198 OTP_MSG(("%s: buffer too small, should be at least %u\n",
199 __FUNCTION__
, oi
->hwlim
- oi
->hwbase
));
205 if (!(oi
->prog
& OTPS_GUP_SW
)) {
206 OTP_MSG(("%s: s/w region not programmed\n", __FUNCTION__
));
209 if (wlen
< (sz
= (uint
)oi
->swlim
- oi
->swbase
)) {
210 OTP_MSG(("%s: buffer too small should be at least %u\n",
211 __FUNCTION__
, oi
->swlim
- oi
->swbase
));
217 if (!(oi
->prog
& OTPS_GUP_CI
)) {
218 OTP_MSG(("%s: chipid region not programmed\n", __FUNCTION__
));
221 if (wlen
< (sz
= OTPGU_CI_SZ
)) {
222 OTP_MSG(("%s: buffer too small, should be at least %u\n",
223 __FUNCTION__
, OTPGU_CI_SZ
));
229 if (!(oi
->prog
& OTPS_GUP_FUSE
)) {
230 OTP_MSG(("%s: fuse region not programmed\n", __FUNCTION__
));
233 if (wlen
< (sz
= (uint
)oi
->flim
- oi
->fbase
)) {
234 OTP_MSG(("%s: buffer too small, should be at least %u\n",
235 __FUNCTION__
, oi
->flim
- oi
->fbase
));
241 OTP_MSG(("%s: reading region %d is not supported\n", __FUNCTION__
, region
));
245 idx
= sb_coreidx(oi
->sbh
);
246 cc
= sb_setcore(oi
->sbh
, SB_CC
, 0);
249 for (i
= 0; i
< sz
; i
++)
250 data
[i
] = otpr(oh
, cc
, base
+ i
);
252 sb_setcoreidx(oi
->sbh
, idx
);
259 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
260 return (int)(oi
->hwprot
| oi
->prog
);
266 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
267 return (int)oi
->size
* 2;
271 otp_nvread(void *oh
, char *data
, uint
*len
)
278 otp_write_bit(otpinfo_t
*oi
, chipcregs_t
*cc
, uint idx
)
283 row
= idx
/ oi
->cols
;
284 col
= idx
% oi
->cols
;
286 otpp
= OTPP_START_BUSY
|
287 ((1 << OTPP_VALUE_SHIFT
) & OTPP_VALUE_MASK
) |
288 ((OTPPOC_BIT_PROG
<< OTPP_OC_SHIFT
) & OTPP_OC_MASK
) |
289 ((row
<< OTPP_ROW_SHIFT
) & OTPP_ROW_MASK
) |
290 ((col
<< OTPP_COL_SHIFT
) & OTPP_COL_MASK
);
291 OTP_MSG(("%s: idx = %d, row = %d, col = %d, otpp = 0x%x\n",
292 __FUNCTION__
, idx
, row
, col
, otpp
));
293 W_REG(oi
->osh
, &cc
->otpprog
, otpp
);
296 ((st
= R_REG(oi
->osh
, &cc
->otpprog
)) & OTPP_START_BUSY
) && (k
< OTPP_TRIES
);
299 if (k
>= OTPP_TRIES
) {
300 OTP_MSG(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__
, st
, k
));
308 otpwb16(otpinfo_t
*oi
, chipcregs_t
*cc
, int wn
, uint16 data
)
314 for (i
= 0; i
< 16; i
++) {
315 if (data
& (1 << i
)) {
316 if ((rc
= otp_write_bit(oi
, cc
, base
+ i
)))
324 /* expects the caller to disable interrupts before calling this routine */
326 otp_write_region(void *oh
, int region
, uint16
*data
, uint wlen
)
328 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
333 /* Validate region selection */
336 if (oi
->prog
& OTPS_GUP_HW
) {
337 OTP_MSG(("%s: h/w region has been programmed\n", __FUNCTION__
));
340 if (wlen
> (uint
)(oi
->hwlim
- oi
->hwbase
)) {
341 OTP_MSG(("%s: wlen %u exceeds OTP h/w region limit %u\n",
342 __FUNCTION__
, wlen
, oi
->hwlim
- oi
->hwbase
));
348 if (oi
->prog
& OTPS_GUP_SW
) {
349 OTP_MSG(("%s: s/w region has been programmed\n", __FUNCTION__
));
352 if (wlen
> (uint
)(oi
->swlim
- oi
->swbase
)) {
353 OTP_MSG(("%s: wlen %u exceeds OTP s/w region limit %u\n",
354 __FUNCTION__
, wlen
, oi
->swlim
- oi
->swbase
));
360 if (oi
->prog
& OTPS_GUP_CI
) {
361 OTP_MSG(("%s: chipid region has been programmed\n", __FUNCTION__
));
364 if (wlen
> OTPGU_CI_SZ
) {
365 OTP_MSG(("%s: wlen %u exceeds OTP ci region limit %u\n",
366 __FUNCTION__
, wlen
, OTPGU_CI_SZ
));
372 if (oi
->prog
& OTPS_GUP_FUSE
) {
373 OTP_MSG(("%s: fuse region has been programmed\n", __FUNCTION__
));
376 if (wlen
> (uint
)(oi
->flim
- oi
->fbase
)) {
377 OTP_MSG(("%s: wlen %u exceeds OTP ci region limit %u\n",
378 __FUNCTION__
, wlen
, oi
->flim
- oi
->fbase
));
381 base
= oi
->flim
- wlen
;
384 OTP_MSG(("%s: writing region %d is not supported\n", __FUNCTION__
, region
));
388 idx
= sb_coreidx(oi
->sbh
);
389 cc
= sb_setcore(oi
->sbh
, SB_CC
, 0);
392 OR_REG(oi
->osh
, &cc
->otpcontrol
, OTPC_PROGEN
);
395 for (i
= 0; i
< wlen
; i
++)
396 otpwb16(oh
, cc
, base
+ i
, data
[i
]);
398 /* Update boundary/flag in memory and in OTP */
401 otpwb16(oh
, cc
, OTPGU_HSB_OFF
, (base
+ i
) * 16);
402 otp_write_bit(oh
, cc
, OTPGU_HWP_OFF
);
405 otpwb16(oh
, cc
, OTPGU_HSB_OFF
, base
* 16);
406 otpwb16(oh
, cc
, OTPGU_SFB_OFF
, (base
+ i
) * 16);
407 otp_write_bit(oh
, cc
, OTPGU_SWP_OFF
);
410 otp_write_bit(oh
, cc
, OTPGU_CIP_OFF
);
413 otpwb16(oh
, cc
, OTPGU_SFB_OFF
, base
* 16);
414 otp_write_bit(oh
, cc
, OTPGU_FUSEP_OFF
);
419 AND_REG(oi
->osh
, &cc
->otpcontrol
, ~OTPC_PROGEN
);
421 /* Sync region info by retrieving them again */
424 sb_setcoreidx(oi
->sbh
, idx
);
428 /* expects the caller to disable interrupts before calling this routine */
430 otp_nvwrite(void *oh
, uint16
*data
, uint wlen
)
434 #endif /* BCMNVRAMW */
438 otp_read_bit(otpinfo_t
*oi
, chipcregs_t
*cc
, uint idx
)
443 row
= idx
/ oi
->cols
;
444 col
= idx
% oi
->cols
;
446 otpp
= OTPP_START_BUSY
|
447 ((OTPPOC_READ
<< OTPP_OC_SHIFT
) & OTPP_OC_MASK
) |
448 ((row
<< OTPP_ROW_SHIFT
) & OTPP_ROW_MASK
) |
449 ((col
<< OTPP_COL_SHIFT
) & OTPP_COL_MASK
);
450 OTP_MSG(("%s: idx = %d, row = %d, col = %d, otpp = 0x%x",
451 __FUNCTION__
, idx
, row
, col
, otpp
));
452 W_REG(oi
->osh
, &cc
->otpprog
, otpp
);
455 ((st
= R_REG(oi
->osh
, &cc
->otpprog
)) & OTPP_START_BUSY
) && (k
< OTPP_TRIES
);
458 if (k
>= OTPP_TRIES
) {
459 OTP_MSG(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__
, st
, k
));
462 if (st
& OTPP_READERR
) {
463 OTP_MSG(("\n%s: Could not read OTP bit %d\n", __FUNCTION__
, idx
));
466 st
= (st
& OTPP_VALUE_MASK
) >> OTPP_VALUE_SHIFT
;
468 OTP_MSG((" => %d\n", st
));
473 otprb16(otpinfo_t
*oi
, chipcregs_t
*cc
, uint wn
)
482 for (i
= 0; i
< 16; i
++) {
483 if ((bit
= otp_read_bit(oi
, cc
, base
+ i
)) == -1)
485 val
= val
| (bit
<< i
);
494 otp_dump(void *oh
, int arg
, char *buf
, uint size
)
496 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
502 idx
= sb_coreidx(oi
->sbh
);
503 cc
= sb_setcore(oi
->sbh
, SB_CC
, 0);
505 count
= otp_size(oh
);
507 bcm_binit(&b
, buf
, size
);
508 for (i
= 0; i
< count
/ 2; i
++) {
510 bcm_bprintf(&b
, "\n0x%04x:", 2 * i
);
512 val
= otpr(oh
, cc
, i
);
514 val
= otprb16(oh
, cc
, i
);
515 bcm_bprintf(&b
, " 0x%04x", val
);
517 bcm_bprintf(&b
, "\n");
519 sb_setcoreidx(oi
->sbh
, idx
);
521 return ((int)(b
.buf
- b
.origbuf
));
525 #else /* BCMHNDOTP - Older HND OTP controller */
527 /* Fields in otpstatus */
528 #define OTPS_PROGFAIL 0x80000000
529 #define OTPS_PROTECT 0x00000007
530 #define OTPS_HW_PROTECT 0x00000001
531 #define OTPS_SW_PROTECT 0x00000002
532 #define OTPS_CID_PROTECT 0x00000004
534 /* Fields in the otpcontrol register */
535 #define OTPC_RECWAIT 0xff000000
536 #define OTPC_PROGWAIT 0x00ffff00
537 #define OTPC_PRW_SHIFT 8
538 #define OTPC_MAXFAIL 0x00000038
539 #define OTPC_VSEL 0x00000006
540 #define OTPC_SELVL 0x00000001
542 /* Fields in otpprog */
543 #define OTPP_COL_MASK 0x000000ff
544 #define OTPP_ROW_MASK 0x0000ff00
545 #define OTPP_ROW_SHIFT 8
546 #define OTPP_READERR 0x10000000
547 #define OTPP_VALUE 0x20000000
548 #define OTPP_VALUE_SHIFT 29
549 #define OTPP_READ 0x40000000
550 #define OTPP_START 0x80000000
551 #define OTPP_BUSY 0x80000000
553 /* OTP regions (Byte offsets from otp size) */
554 #define OTP_SWLIM_OFF (-8)
555 #define OTP_CIDBASE_OFF 0
556 #define OTP_CIDLIM_OFF 8
558 /* Predefined OTP words (Word offset from otp size) */
559 #define OTP_BOUNDARY_OFF (-4)
560 #define OTP_HWSIGN_OFF (-3)
561 #define OTP_SWSIGN_OFF (-2)
562 #define OTP_CIDSIGN_OFF (-1)
563 #define OTP_CID_OFF 0
564 #define OTP_PKG_OFF 1
565 #define OTP_FID_OFF 2
566 #define OTP_RSV_OFF 3
567 #define OTP_LIM_OFF 4
569 #define OTP_HW_REGION OTPS_HW_PROTECT
570 #define OTP_SW_REGION OTPS_SW_PROTECT
571 #define OTP_CID_REGION OTPS_CID_PROTECT
573 #if OTP_HW_REGION != OTP_HW_RGN
574 #error "incompatible OTP_HW_RGN"
576 #if OTP_SW_REGION != OTP_SW_RGN
577 #error "incompatible OTP_SW_RGN"
579 #if OTP_CID_REGION != OTP_CI_RGN
580 #error "incompatible OTP_CI_RGN"
583 #define OTP_SIGNATURE 0x578a
584 #define OTP_MAGIC 0x4e56
586 #define OTPP_TRIES 10000000 /* # of tries for OTPP */
588 typedef struct _otpinfo
{
589 sb_t
*sbh
; /* Saved sb handle */
590 uint ccrev
; /* chipc revision */
591 uint size
; /* Size of otp in bytes */
592 uint hwprot
; /* Hardware protection bits */
593 uint signvalid
; /* Signature valid bits */
594 int boundary
; /* hw/sw boundary */
597 static otpinfo_t otpinfo
;
599 static uint16
otproff(void *oh
, chipcregs_t
*cc
, int woff
);
601 static int otp_write_word(void *oh
, chipcregs_t
*cc
, int wn
, uint16 data
);
602 #endif /* BCMNVRAMW */
605 otpr(void *oh
, chipcregs_t
*cc
, uint wn
)
607 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
611 ASSERT(wn
< ((((otpinfo_t
*)oh
)->size
/ 2) + OTP_LIM_OFF
));
614 osh
= sb_osh(oi
->sbh
);
616 ptr
= (uint16
*)((uchar
*)cc
+ CC_OTP
);
617 return (R_REG(osh
, &ptr
[wn
]));
621 otproff(void *oh
, chipcregs_t
*cc
, int woff
)
623 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
627 ASSERT(woff
>= (-((int)oi
->size
/ 2)));
628 ASSERT(woff
< OTP_LIM_OFF
);
631 osh
= sb_osh(oi
->sbh
);
633 ptr
= (uint16
*)((uchar
*)cc
+ CC_OTP
);
635 return (R_REG(osh
, &ptr
[(oi
->size
/ 2) + woff
]));
649 bzero(oi
, sizeof(otpinfo_t
));
651 idx
= sb_coreidx(sbh
);
654 osh
= sb_osh(oi
->sbh
);
657 if ((cc
= sb_setcore(sbh
, SB_CC
, 0)) != NULL
) {
658 cap
= R_REG(osh
, &cc
->capabilities
);
659 if ((cap
& CC_CAP_OTPSIZE
) == 0) {
665 oi
->ccrev
= sb_chipcrev(sbh
);
667 /* As of right now, support only 4320a2 and 4311a1 */
668 if ((oi
->ccrev
!= 12) && (oi
->ccrev
!= 17)) {
672 oi
->size
= 1 << (((cap
& CC_CAP_OTPSIZE
) >> CC_CAP_OTPSIZE_SHIFT
)
673 + CC_CAP_OTPSIZE_BASE
);
675 oi
->hwprot
= (int)(R_REG(osh
, &cc
->otpstatus
) & OTPS_PROTECT
);
678 if (oi
->ccrev
!= 17) {
679 if (otproff(oi
, cc
, OTP_HWSIGN_OFF
) == OTP_SIGNATURE
) {
680 oi
->signvalid
|= OTP_HW_REGION
;
681 oi
->boundary
= otproff(oi
, cc
, OTP_BOUNDARY_OFF
);
684 if (otproff(oi
, cc
, OTP_SWSIGN_OFF
) == OTP_SIGNATURE
)
685 oi
->signvalid
|= OTP_SW_REGION
;
687 if (otproff(oi
, cc
, OTP_CIDSIGN_OFF
) == OTP_SIGNATURE
)
688 oi
->signvalid
|= OTP_CID_REGION
;
695 sb_setcoreidx(sbh
, idx
);
701 otp_read_region(void *oh
, int region
, uint16
*data
, uint wlen
)
709 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
710 return ((int)(oi
->hwprot
| oi
->signvalid
));
716 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
717 return ((int)(oi
->size
));
721 otp_nvread(void *oh
, char *data
, uint
*len
)
724 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
725 uint32 base
, bound
, lim
= 0, st
;
726 int i
, chunk
, gchunks
, tsz
= 0;
730 uint16
*rawotp
= NULL
;
732 /* save the orig core */
733 idx
= sb_coreidx(oi
->sbh
);
734 cc
= sb_setcore(oi
->sbh
, SB_CC
, 0);
737 if (!(st
& (OTP_HW_REGION
| OTP_SW_REGION
))) {
738 OTP_MSG(("OTP not programmed\n"));
743 /* Read the whole otp so we can easily manipulate it */
745 if ((rawotp
= MALLOC(sb_osh(oi
->sbh
), lim
)) == NULL
) {
746 OTP_MSG(("Out of memory for rawotp\n"));
750 for (i
= 0; i
< (lim
/ 2); i
++)
751 rawotp
[i
] = otpr(oh
, cc
, i
);
753 if ((st
& OTP_HW_REGION
) == 0) {
754 OTP_MSG(("otp: hw region not written (0x%x)\n", st
));
756 /* This could be a programming failure in the first
757 * chunk followed by one or more good chunks
759 for (i
= 0; i
< (lim
/ 2); i
++)
760 if (rawotp
[i
] == OTP_MAGIC
)
765 bound
= (i
* 2) + rawotp
[i
+ 1];
766 OTP_MSG(("otp: trying chunk at 0x%x-0x%x\n", i
* 2, bound
));
768 OTP_MSG(("otp: unprogrammed\n"));
773 bound
= rawotp
[(lim
/ 2) + OTP_BOUNDARY_OFF
];
775 /* There are two cases: 1) The whole otp is used as nvram
776 * and 2) There is a hardware header followed by nvram.
778 if (rawotp
[0] == OTP_MAGIC
) {
780 if (bound
!= rawotp
[1])
781 OTP_MSG(("otp: Bound 0x%x != chunk0 len 0x%x\n", bound
,
787 /* Find and copy the data */
793 while ((i
< (lim
/ 2)) && (rawotp
[i
] == OTP_MAGIC
)) {
794 int dsz
, rsz
= rawotp
[i
+ 1];
796 if (((i
* 2) + rsz
) >= lim
) {
797 OTP_MSG((" bad chunk size, chunk %d, base 0x%x, size 0x%x\n",
799 /* Bad length, try to find another chunk anyway */
802 if (hndcrc16((uint8
*)&rawotp
[i
], rsz
,
803 CRC16_INIT_VALUE
) == CRC16_GOOD_VALUE
) {
804 /* Good crc, copy the vars */
805 OTP_MSG((" good chunk %d, base 0x%x, size 0x%x\n",
810 if (offset
+ dsz
>= *len
) {
811 OTP_MSG(("Out of memory for otp\n"));
814 bcopy((char *)&rawotp
[i
+ 2], &data
[offset
], dsz
);
816 /* Remove extra null characters at the end */
818 data
[offset
- 1] == 0 && data
[offset
- 2] == 0)
822 /* bad length or crc didn't check, try to find the next set */
823 OTP_MSG((" chunk %d @ 0x%x size 0x%x: bad crc, ",
825 if (rawotp
[i
+ (rsz
/ 2)] == OTP_MAGIC
) {
826 /* Assume length is good */
829 while (++i
< (lim
/ 2))
830 if (rawotp
[i
] == OTP_MAGIC
)
834 OTP_MSG(("trying next base 0x%x\n", i
* 2));
836 OTP_MSG(("no more chunks\n"));
841 OTP_MSG((" otp size = %d, boundary = 0x%x, nv base = 0x%x\n",
844 OTP_MSG((" Found %d bytes in %d good chunks out of %d\n",
845 tsz
, gchunks
, chunk
));
847 OTP_MSG((" No good chunks found out of %d\n", chunk
));
853 MFREE(sb_osh(oi
->sbh
), rawotp
, lim
);
854 sb_setcoreidx(oi
->sbh
, idx
);
862 otp_write_word(void *oh
, chipcregs_t
*cc
, int wn
, uint16 data
)
864 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
865 uint base
, row
, col
, bit
, i
, j
, k
;
866 uint32 pwait
, init_pwait
, otpc
, otpp
, pst
, st
;
869 OTP_MSG(("%s: [0x%x] = 0x%x\n", __FUNCTION__
, wn
* 2, data
));
870 #endif /* OTP_FORCEFAIL */
872 /* This is bit-at-a-time writing, future cores may do word-at-a-time */
873 base
= (wn
* 16) + (wn
/ 4);
874 if (oi
->ccrev
== 12) {
876 init_pwait
= 0x00000200;
879 init_pwait
= 0x00004000;
881 for (i
= 0; i
< 16; i
++) {
884 row
= (base
+ i
) / 65;
885 col
= (base
+ i
) % 65;
887 ((bit
<< OTPP_VALUE_SHIFT
) & OTPP_VALUE
) |
888 ((row
<< OTPP_ROW_SHIFT
) & OTPP_ROW_MASK
) |
889 (col
& OTPP_COL_MASK
);
890 OTP_MSG(("row %d, col %d, val %d, otpc 0x%x, otpp 0x%x\n", row
, col
, bit
,
895 OTP_MSG((" %d: pwait %d\n", j
, (pwait
>> 8)));
896 W_REG(osh
, &cc
->otpcontrol
, otpc
| pwait
);
897 W_REG(osh
, &cc
->otpprog
, otpp
);
898 pst
= R_REG(osh
, &cc
->otpprog
);
899 for (k
= 0; ((pst
& OTPP_BUSY
) == OTPP_BUSY
) && (k
< OTPP_TRIES
); k
++)
900 pst
= R_REG(osh
, &cc
->otpprog
);
901 if (k
>= OTPP_TRIES
) {
902 OTP_MSG(("BUSY stuck: pst=0x%x, count=%d\n", pst
, k
));
906 st
= R_REG(osh
, &cc
->otpstatus
);
907 if (((st
& OTPS_PROGFAIL
) == 0) || (pwait
== OTPC_PROGWAIT
)) {
910 if ((oi
->ccrev
== 12) && (pwait
>= 0x1000))
911 pwait
= (pwait
<< 3) & OTPC_PROGWAIT
;
913 pwait
= (pwait
<< 1) & OTPC_PROGWAIT
;
915 pwait
= OTPC_PROGWAIT
;
918 if (st
& OTPS_PROGFAIL
) {
919 OTP_MSG(("After %d tries: otpc = 0x%x, otpp = 0x%x/0x%x, otps = 0x%x\n",
920 j
, otpc
| pwait
, otpp
, pst
, st
));
921 OTP_MSG(("otp prog failed. wn=%d, bit=%d, ppret=%d, ret=%d\n",
930 /* expects the caller to disable interrupts before calling this routine */
932 otp_write_region(void *oh
, int region
, uint16
*data
, uint wlen
)
934 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
936 uint wn
, base
= 0, lim
;
941 idx
= sb_coreidx(oi
->sbh
);
942 cc
= sb_setcore(oi
->sbh
, SB_CC
, 0);
944 /* Run bist on chipc to get any unprogrammed bits into a known state */
945 if (sb_corebist(oi
->sbh
) == 0)
946 OTP_MSG(("%s: bist passed, otp is blank\n", __FUNCTION__
));
948 if (oi
->ccrev
!= 17) {
949 /* Check valid region */
950 if ((region
!= OTP_HW_REGION
) &&
951 (region
!= OTP_SW_REGION
) &&
952 (region
!= OTP_CID_REGION
)) {
957 /* Region already written? */
958 st
= oi
->hwprot
| oi
-> signvalid
;
959 if ((st
& region
) != 0) {
964 /* HW and CID have to be written before SW */
965 if ((st
& OTP_SW_REGION
) != 0) {
970 /* Bounds for the region */
971 lim
= (oi
->size
/ 2) + OTP_SWLIM_OFF
;
972 if (region
== OTP_HW_REGION
) {
974 } else if (region
== OTP_SW_REGION
) {
975 base
= oi
->boundary
/ 2;
976 } else if (region
== OTP_CID_REGION
) {
977 base
= (oi
->size
/ 2) + OTP_CID_OFF
;
978 lim
= (oi
->size
/ 2) + OTP_LIM_OFF
;
984 if (wlen
> (lim
- base
)) {
993 for (wn
= base
; wn
< lim
; wn
++)
994 if (oi
->ccrev
== 17) {
998 werrs
= (otp_write_word(oh
, cc
, rwn
++, *data
) != 0) ? 1 : 0;
999 werrs
+= (otp_write_word(oh
, cc
, rwn
++, *data
) != 0) ? 1 : 0;
1000 werrs
+= (otp_write_word(oh
, cc
, rwn
, *data
++) != 0) ? 1 : 0;
1004 if (otp_write_word(oh
, cc
, wn
, *data
++) != 0)
1007 if (oi
->ccrev
!= 17) {
1008 /* Done with the data, write the signature & boundary if needed */
1009 if (region
== OTP_HW_REGION
) {
1011 if (otp_write_word(oh
, cc
, (oi
->size
/ 2) + OTP_BOUNDARY_OFF
,
1015 if (otp_write_word(oh
, cc
, (oi
->size
/ 2) + OTP_HWSIGN_OFF
,
1016 OTP_SIGNATURE
) != 0)
1018 oi
->boundary
= lim
* 2;
1019 oi
->signvalid
|= OTP_HW_REGION
;
1020 } else if (region
== OTP_SW_REGION
) {
1022 if (otp_write_word(oh
, cc
, (oi
->size
/ 2) + OTP_SWSIGN_OFF
,
1023 OTP_SIGNATURE
) != 0)
1025 oi
->signvalid
|= OTP_SW_REGION
;
1026 } else if (region
== OTP_CID_REGION
) {
1028 if (otp_write_word(oh
, cc
, (oi
->size
/ 2) + OTP_CIDSIGN_OFF
,
1029 OTP_SIGNATURE
) != 0)
1031 oi
->signvalid
|= OTP_CID_REGION
;
1036 OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n",
1037 st_n
, st_s
, st_n
, st_n
?(st_s
/ st_n
):0, st_hwm
, pp_hwm
));
1039 sb_setcoreidx(oi
->sbh
, idx
);
1044 /* expects the caller to disable interrupts before calling this routine */
1046 otp_nvwrite(void *oh
, uint16
*data
, uint wlen
)
1048 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1050 uint16 crc
, clen
, *p
, hdr
[2];
1051 uint wn
, base
= 0, lim
;
1057 /* Run bist on chipc to get any unprogrammed bits into a known state */
1058 if (sb_corebist(oi
->sbh
) == 0)
1059 OTP_MSG(("%s: bist passed, otp is blank\n", __FUNCTION__
));
1061 /* otp already written? */
1062 st
= oi
->hwprot
| oi
-> signvalid
;
1063 if ((st
& (OTP_HW_REGION
| OTP_SW_REGION
)) == (OTP_HW_REGION
| OTP_SW_REGION
))
1066 /* save the orig core */
1067 idx
= sb_coreidx(oi
->sbh
);
1068 cc
= sb_setcore(oi
->sbh
, SB_CC
, 0);
1070 /* Bounds for the region */
1071 lim
= (oi
->size
/ 2) + OTP_SWLIM_OFF
;
1074 /* Look for possible chunks from the end down */
1078 if (otpr(oh
, cc
, wn
) == OTP_MAGIC
) {
1079 base
= wn
+ (otpr(oh
, cc
, wn
+ 1) / 2);
1084 OTP_MSG(("Unprogrammed otp\n"));
1086 OTP_MSG(("Found some chunks, skipping to 0x%x\n", base
* 2));
1088 if ((wlen
+ 3) > (lim
- base
)) {
1089 err
= BCME_NORESOURCE
;
1094 /* Prepare the header and crc */
1096 hdr
[1] = (wlen
+ 3) * 2;
1097 crc
= hndcrc16((uint8
*)hdr
, sizeof(hdr
), CRC16_INIT_VALUE
);
1098 crc
= hndcrc16((uint8
*)data
, wlen
* 2, crc
);
1104 lim
= base
+ wlen
+ 2;
1106 OTP_MSG(("writing chunk, 0x%x bytes @ 0x%x-0x%x\n", wlen
* 2,
1107 base
* 2, (lim
+ 1) * 2));
1109 /* Write the header */
1110 err
= otp_write_word(oh
, cc
, base
, hdr
[0]);
1112 /* Write the data */
1114 err
+= otp_write_word(oh
, cc
, wn
++, *p
++);
1116 /* If there has been an error, close this chunk */
1118 OTP_MSG(("closing early @ 0x%x\n", wn
* 2));
1123 /* If we wrote the whole chunk, write the crc */
1125 OTP_MSG((" whole chunk written, crc = 0x%x\n", crc
));
1126 err
+= otp_write_word(oh
, cc
, wn
++, crc
);
1129 /* If there was an error adjust the count to point to
1130 * the word after the error so we can start the next
1133 clen
= (wn
- base
) * 2;
1134 OTP_MSG((" partial chunk written, chunk len = 0x%x\n", clen
));
1136 /* And now write the chunk length */
1137 err
+= otp_write_word(oh
, cc
, base
+ 1, clen
);
1140 /* Write the signature and boundary if this is the HW region,
1141 * but don't report failure if either of these 2 writes fail.
1143 if (otp_write_word(oh
, cc
, (oi
->size
/ 2) + OTP_BOUNDARY_OFF
, wn
* 2) == 0)
1144 gerr
+= otp_write_word(oh
, cc
, (oi
->size
/ 2) + OTP_HWSIGN_OFF
,
1148 oi
->boundary
= wn
* 2;
1149 oi
->signvalid
|= OTP_HW_REGION
;
1154 /* Errors, do it all over again if there is space left */
1155 if ((wlen
+ 3) <= ((oi
->size
/ 2) + OTP_SWLIM_OFF
- wn
)) {
1157 lim
= base
+ wlen
+ 2;
1158 OTP_MSG(("Programming errors, retry @ 0x%x\n", wn
* 2));
1160 OTP_MSG(("Programming errors, no space left ( 0x%x)\n", wn
* 2));
1166 OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n",
1167 st_n
, st_s
, st_n
, st_s
/ st_n
, st_hwm
, pp_hwm
));
1170 OTP_MSG(("programming %s after %d errors\n", (err
== 0) ? "succedded" : "failed",
1174 sb_setcoreidx(oi
->sbh
, idx
);
1181 #endif /* BCMNVRAMW */
1185 otp_read_bit(void *oh
, chipcregs_t
*cc
, uint idx
)
1190 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1192 osh
= sb_osh(oi
->sbh
);
1196 otpp
= OTPP_START
| OTPP_READ
|
1197 ((row
<< OTPP_ROW_SHIFT
) & OTPP_ROW_MASK
) |
1198 (col
& OTPP_COL_MASK
);
1200 OTP_MSG(("%s: idx = %d, row = %d, col = %d, otpp = 0x%x", __FUNCTION__
,
1201 idx
, row
, col
, otpp
));
1203 W_REG(osh
, &cc
->otpprog
, otpp
);
1204 st
= R_REG(osh
, &cc
->otpprog
);
1205 for (k
= 0; ((st
& OTPP_BUSY
) == OTPP_BUSY
) && (k
< OTPP_TRIES
); k
++)
1206 st
= R_REG(osh
, &cc
->otpprog
);
1208 if (k
>= OTPP_TRIES
) {
1209 OTP_MSG(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__
, st
, k
));
1212 if (st
& OTPP_READERR
) {
1213 OTP_MSG(("\n%s: Could not read OTP bit %d\n", __FUNCTION__
, idx
));
1216 st
= (st
& OTPP_VALUE
) >> OTPP_VALUE_SHIFT
;
1217 OTP_MSG((" => %d\n", st
));
1222 otprb16(void *oh
, chipcregs_t
*cc
, uint wn
)
1227 base
= (wn
* 16) + (wn
/ 4);
1229 for (i
= 0; i
< 16; i
++) {
1230 if ((bit
= otp_read_bit(oh
, cc
, base
+ i
)) == 0xffff)
1232 val
= val
| (bit
<< i
);
1240 otp_dump(void *oh
, int arg
, char *buf
, uint size
)
1242 otpinfo_t
*oi
= (otpinfo_t
*)oh
;
1244 uint idx
, i
, count
, lil
;
1248 idx
= sb_coreidx(oi
->sbh
);
1249 cc
= sb_setcore(oi
->sbh
, SB_CC
, 0);
1254 /* Run bist on chipc to get any unprogrammed bits into a known state */
1255 if (sb_corebist(oi
->sbh
) == 0)
1256 OTP_MSG(("%s: bist passed, otp is blank\n", __FUNCTION__
));
1263 count
= (oi
->size
/ 2) + OTP_LIM_OFF
;
1267 OTP_MSG(("%s: arg %d, size %d, words %d\n", __FUNCTION__
, arg
, size
, count
));
1268 bcm_binit(&b
, buf
, size
);
1269 for (i
= 0; i
< count
; i
++) {
1271 bcm_bprintf(&b
, "0x%04x:", 2 * i
);
1274 val
= otpr(oh
, cc
, i
);
1276 val
= otprb16(oh
, cc
, i
);
1277 bcm_bprintf(&b
, " 0x%04x", val
);
1278 if ((i
& lil
) == lil
) {
1280 bcm_bprintf(&b
, " %d\n",
1281 otp_read_bit(oh
, cc
, ((i
/ 4) * 65) + 64) & 1);
1283 bcm_bprintf(&b
, "\n");
1287 if ((i
& lil
) != lil
)
1288 bcm_bprintf(&b
, "\n");
1290 OTP_MSG(("%s: returning %d, left %d, wn %d\n",
1291 __FUNCTION__
, (int)(b
.buf
- b
.origbuf
), b
.size
, i
));
1293 sb_setcoreidx(oi
->sbh
, idx
);
1295 return ((int)(b
.buf
- b
.origbuf
));
1299 #endif /* BCMHNDOTP */