2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <linux/kernel.h>
18 #include <linux/string.h>
25 #include <bcmendian.h>
29 #include "siutils_priv.h"
32 * There are two different OTP controllers so far:
33 * 1. new IPX OTP controller: chipc 21, >=23
34 * 2. older HND OTP controller: chipc 12, 17, 22
36 * Define BCMHNDOTP to include support for the HND OTP controller.
37 * Define BCMIPXOTP to include support for the IPX OTP controller.
39 * NOTE 1: More than one may be defined
40 * NOTE 2: If none are defined, the default is to include them all.
43 #if !defined(BCMHNDOTP) && !defined(BCMIPXOTP)
48 #define OTPTYPE_HND(ccrev) ((ccrev) < 21 || (ccrev) == 22)
49 #define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23)
51 #define OTPP_TRIES 10000000 /* # of tries for OTPP */
54 #define MAXNUMRDES 9 /* Maximum OTP redundancy entries */
57 /* OTP common function type */
58 typedef int (*otp_status_t) (void *oh);
59 typedef int (*otp_size_t) (void *oh);
60 typedef void *(*otp_init_t) (si_t *sih);
61 typedef u16(*otp_read_bit_t) (void *oh, chipcregs_t *cc, uint off);
62 typedef int (*otp_read_region_t) (si_t *sih, int region, u16 *data,
64 typedef int (*otp_nvread_t) (void *oh, char *data, uint *len);
66 /* OTP function struct */
67 typedef struct otp_fn_s {
69 otp_read_bit_t read_bit;
71 otp_read_region_t read_region;
77 uint ccrev; /* chipc revision */
78 otp_fn_t *fn; /* OTP functions */
79 si_t *sih; /* Saved sb handle */
84 u16 wsize; /* Size of otp in words */
85 u16 rows; /* Geometry */
86 u16 cols; /* Geometry */
87 u32 status; /* Flag bits (lock/prog/rv).
88 * (Reflected only when OTP is power cycled)
90 u16 hwbase; /* hardware subregion offset */
91 u16 hwlim; /* hardware subregion boundary */
92 u16 swbase; /* software subregion offset */
93 u16 swlim; /* software subregion boundary */
94 u16 fbase; /* fuse subregion offset */
95 u16 flim; /* fuse subregion boundary */
96 int otpgu_base; /* offset to General Use Region */
97 #endif /* BCMIPXOTP */
100 /* HND OTP section */
101 uint size; /* Size of otp in bytes */
102 uint hwprot; /* Hardware protection bits */
103 uint signvalid; /* Signature valid bits */
104 int boundary; /* hw/sw boundary */
105 #endif /* BCMHNDOTP */
108 static otpinfo_t otpinfo;
113 * Exported functions:
118 * ipxotp_read_region()
125 #define HWSW_RGN(rgn) (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
128 /* CC revs 21, 24 and 27 OTP General Use Region word offset */
129 #define REVA4_OTPGU_BASE 12
131 /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
132 #define REVB8_OTPGU_BASE 20
134 /* CC rev 36 OTP General Use Region word offset */
135 #define REV36_OTPGU_BASE 12
137 /* Subregion word offsets in General Use region */
138 #define OTPGU_HSB_OFF 0
139 #define OTPGU_SFB_OFF 1
140 #define OTPGU_CI_OFF 2
141 #define OTPGU_P_OFF 3
142 #define OTPGU_SROM_OFF 4
144 /* Flag bit offsets in General Use region */
145 #define OTPGU_HWP_OFF 60
146 #define OTPGU_SWP_OFF 61
147 #define OTPGU_CIP_OFF 62
148 #define OTPGU_FUSEP_OFF 63
149 #define OTPGU_CIP_MSK 0x4000
150 #define OTPGU_P_MSK 0xf000
151 #define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16)
154 #define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */
155 #define OTP_SZ_FU_288 (288/8) /* 288 bits */
156 #define OTP_SZ_FU_216 (216/8) /* 216 bits */
157 #define OTP_SZ_FU_72 (72/8) /* 72 bits */
158 #define OTP_SZ_CHECKSUM (16/8) /* 16 bits */
159 #define OTP4315_SWREG_SZ 178 /* 178 bytes */
160 #define OTP_SZ_FU_144 (144/8) /* 144 bits */
162 static int ipxotp_status(void *oh)
164 otpinfo_t *oi = (otpinfo_t *) oh;
165 return (int)(oi->status);
168 /* Return size in bytes */
169 static int ipxotp_size(void *oh)
171 otpinfo_t *oi = (otpinfo_t *) oh;
172 return (int)oi->wsize * 2;
175 static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
179 oi = (otpinfo_t *) oh;
181 ASSERT(wn < oi->wsize);
184 return R_REG(oi->osh, &cc->sromotp[wn]);
187 static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
189 otpinfo_t *oi = (otpinfo_t *) oh;
193 row = off / oi->cols;
194 col = off % oi->cols;
196 otpp = OTPP_START_BUSY |
197 ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
198 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
199 ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
200 W_REG(oi->osh, &cc->otpprog, otpp);
203 ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY)
204 && (k < OTPP_TRIES); k++)
206 if (k >= OTPP_TRIES) {
209 if (st & OTPP_READERR) {
212 st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
217 /* Calculate max HW/SW region byte size by substracting fuse region and checksum size,
218 * osizew is oi->wsize (OTP size - GU size) in words
220 static int ipxotp_max_rgnsz(si_t *sih, int osizew)
224 switch (CHIPID(sih->chip)) {
225 case BCM43224_CHIP_ID:
226 case BCM43225_CHIP_ID:
227 ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
229 case BCM4313_CHIP_ID:
230 ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
233 ASSERT(0); /* Don't konw about this chip */
239 static void _ipxotp_init(otpinfo_t *oi, chipcregs_t *cc)
244 /* record word offset of General Use Region for various chipcommon revs */
245 if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
246 || oi->sih->ccrev == 27) {
247 oi->otpgu_base = REVA4_OTPGU_BASE;
248 } else if (oi->sih->ccrev == 36) {
249 /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
250 if (oi->wsize >= 128)
251 oi->otpgu_base = REVB8_OTPGU_BASE;
253 oi->otpgu_base = REV36_OTPGU_BASE;
254 } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
255 oi->otpgu_base = REVB8_OTPGU_BASE;
258 /* First issue an init command so the status is up to date */
260 OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
262 W_REG(oi->osh, &cc->otpprog, otpp);
264 ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY)
265 && (k < OTPP_TRIES); k++)
267 if (k >= OTPP_TRIES) {
271 /* Read OTP lock bits and subregion programmed indication bits */
272 oi->status = R_REG(oi->osh, &cc->otpstatus);
274 if ((CHIPID(oi->sih->chip) == BCM43224_CHIP_ID)
275 || (CHIPID(oi->sih->chip) == BCM43225_CHIP_ID)) {
278 (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
281 oi->status |= (p_bits << OTPS_GUP_SHIFT);
285 * h/w region base and fuse region limit are fixed to the top and
286 * the bottom of the general use region. Everything else can be flexible.
288 oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
289 oi->hwlim = oi->wsize;
290 if (oi->status & OTPS_GUP_HW) {
292 ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
293 oi->swbase = oi->hwlim;
295 oi->swbase = oi->hwbase;
297 /* subtract fuse and checksum from beginning */
298 oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
300 if (oi->status & OTPS_GUP_SW) {
302 ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
303 oi->fbase = oi->swlim;
305 oi->fbase = oi->swbase;
307 oi->flim = oi->wsize;
310 static void *ipxotp_init(si_t *sih)
316 /* Make sure we're running IPX OTP */
317 ASSERT(OTPTYPE_IPX(sih->ccrev));
318 if (!OTPTYPE_IPX(sih->ccrev))
321 /* Make sure OTP is not disabled */
322 if (si_is_otp_disabled(sih)) {
326 /* Make sure OTP is powered up */
327 if (!si_is_otp_powered(sih)) {
333 /* Check for otp size */
334 switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
353 case 7: /* 16x64 *//* 1024 bits */
359 /* Don't know the geometry */
363 /* Retrieve OTP region info */
364 idx = si_coreidx(sih);
365 cc = si_setcoreidx(sih, SI_CC_IDX);
368 _ipxotp_init(oi, cc);
370 si_setcoreidx(sih, idx);
375 static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
377 otpinfo_t *oi = (otpinfo_t *) oh;
382 /* Validate region selection */
385 sz = (uint) oi->hwlim - oi->hwbase;
386 if (!(oi->status & OTPS_GUP_HW)) {
388 return BCME_NOTFOUND;
392 return BCME_BUFTOOSHORT;
397 sz = ((uint) oi->swlim - oi->swbase);
398 if (!(oi->status & OTPS_GUP_SW)) {
400 return BCME_NOTFOUND;
404 return BCME_BUFTOOSHORT;
410 if (!(oi->status & OTPS_GUP_CI)) {
412 return BCME_NOTFOUND;
416 return BCME_BUFTOOSHORT;
418 base = oi->otpgu_base + OTPGU_CI_OFF;
421 sz = (uint) oi->flim - oi->fbase;
422 if (!(oi->status & OTPS_GUP_FUSE)) {
424 return BCME_NOTFOUND;
428 return BCME_BUFTOOSHORT;
433 sz = ((uint) oi->flim - oi->hwbase);
434 if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
436 return BCME_NOTFOUND;
440 return BCME_BUFTOOSHORT;
448 idx = si_coreidx(oi->sih);
449 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
453 for (i = 0; i < sz; i++)
454 data[i] = ipxotp_otpr(oh, cc, base + i);
456 si_setcoreidx(oi->sih, idx);
461 static int ipxotp_nvread(void *oh, char *data, uint *len)
463 return BCME_UNSUPPORTED;
466 static otp_fn_t ipxotp_fn = {
467 (otp_size_t) ipxotp_size,
468 (otp_read_bit_t) ipxotp_read_bit,
470 (otp_init_t) ipxotp_init,
471 (otp_read_region_t) ipxotp_read_region,
472 (otp_nvread_t) ipxotp_nvread,
474 (otp_status_t) ipxotp_status
477 #endif /* BCMIPXOTP */
482 * Exported functions:
487 * hndotp_read_region()
494 /* Fields in otpstatus */
495 #define OTPS_PROGFAIL 0x80000000
496 #define OTPS_PROTECT 0x00000007
497 #define OTPS_HW_PROTECT 0x00000001
498 #define OTPS_SW_PROTECT 0x00000002
499 #define OTPS_CID_PROTECT 0x00000004
500 #define OTPS_RCEV_MSK 0x00003f00
501 #define OTPS_RCEV_SHIFT 8
503 /* Fields in the otpcontrol register */
504 #define OTPC_RECWAIT 0xff000000
505 #define OTPC_PROGWAIT 0x00ffff00
506 #define OTPC_PRW_SHIFT 8
507 #define OTPC_MAXFAIL 0x00000038
508 #define OTPC_VSEL 0x00000006
509 #define OTPC_SELVL 0x00000001
511 /* OTP regions (Word offsets from otp size) */
512 #define OTP_SWLIM_OFF (-4)
513 #define OTP_CIDBASE_OFF 0
514 #define OTP_CIDLIM_OFF 4
516 /* Predefined OTP words (Word offset from otp size) */
517 #define OTP_BOUNDARY_OFF (-4)
518 #define OTP_HWSIGN_OFF (-3)
519 #define OTP_SWSIGN_OFF (-2)
520 #define OTP_CIDSIGN_OFF (-1)
521 #define OTP_CID_OFF 0
522 #define OTP_PKG_OFF 1
523 #define OTP_FID_OFF 2
524 #define OTP_RSV_OFF 3
525 #define OTP_LIM_OFF 4
526 #define OTP_RD_OFF 4 /* Redundancy row starts here */
527 #define OTP_RC0_OFF 28 /* Redundancy control word 1 */
528 #define OTP_RC1_OFF 32 /* Redundancy control word 2 */
529 #define OTP_RC_LIM_OFF 36 /* Redundancy control word end */
531 #define OTP_HW_REGION OTPS_HW_PROTECT
532 #define OTP_SW_REGION OTPS_SW_PROTECT
533 #define OTP_CID_REGION OTPS_CID_PROTECT
535 #if OTP_HW_REGION != OTP_HW_RGN
536 #error "incompatible OTP_HW_RGN"
538 #if OTP_SW_REGION != OTP_SW_RGN
539 #error "incompatible OTP_SW_RGN"
541 #if OTP_CID_REGION != OTP_CI_RGN
542 #error "incompatible OTP_CI_RGN"
545 /* Redundancy entry definitions */
546 #define OTP_RCE_ROW_SZ 6
547 #define OTP_RCE_SIGN_MASK 0x7fff
548 #define OTP_RCE_ROW_MASK 0x3f
549 #define OTP_RCE_BITS 21
550 #define OTP_RCE_SIGN_SZ 15
551 #define OTP_RCE_BIT0 1
554 #define OTP_SIGNATURE 0x578a
555 #define OTP_MAGIC 0x4e56
557 static int hndotp_status(void *oh)
559 otpinfo_t *oi = (otpinfo_t *) oh;
560 return (int)(oi->hwprot | oi->signvalid);
563 static int hndotp_size(void *oh)
565 otpinfo_t *oi = (otpinfo_t *) oh;
566 return (int)(oi->size);
569 static u16 hndotp_otpr(void *oh, chipcregs_t *cc, uint wn)
571 otpinfo_t *oi = (otpinfo_t *) oh;
575 ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF));
578 osh = si_osh(oi->sih);
580 ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
581 return R_REG(osh, &ptr[wn]);
584 static u16 hndotp_otproff(void *oh, chipcregs_t *cc, int woff)
586 otpinfo_t *oi = (otpinfo_t *) oh;
590 ASSERT(woff >= (-((int)oi->size / 2)));
591 ASSERT(woff < OTP_LIM_OFF);
594 osh = si_osh(oi->sih);
596 ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
598 return R_REG(osh, &ptr[(oi->size / 2) + woff]);
601 static u16 hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx)
603 otpinfo_t *oi = (otpinfo_t *) oh;
608 osh = si_osh(oi->sih);
612 otpp = OTPP_START_BUSY | OTPP_READ |
613 ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | (col & OTPP_COL_MASK);
615 W_REG(osh, &cc->otpprog, otpp);
616 st = R_REG(osh, &cc->otpprog);
618 ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES);
620 st = R_REG(osh, &cc->otpprog);
622 if (k >= OTPP_TRIES) {
625 if (st & OTPP_READERR) {
628 st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
632 static void *hndotp_init(si_t *sih)
637 u32 cap = 0, clkdiv, otpdiv = 0;
643 idx = si_coreidx(sih);
644 osh = si_osh(oi->sih);
647 cc = si_setcoreidx(sih, SI_CC_IDX);
649 cap = R_REG(osh, &cc->capabilities);
650 if ((cap & CC_CAP_OTPSIZE) == 0) {
655 /* As of right now, support only 4320a2, 4311a1 and 4312 */
656 ASSERT((oi->ccrev == 12) || (oi->ccrev == 17)
657 || (oi->ccrev == 22));
659 ((oi->ccrev == 12) || (oi->ccrev == 17)
660 || (oi->ccrev == 22)))
663 /* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is
664 * 8 row (64 bytes) smaller
667 1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT)
668 + CC_CAP_OTPSIZE_BASE);
670 oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2);
672 oi->hwprot = (int)(R_REG(osh, &cc->otpstatus) & OTPS_PROTECT);
675 /* Check the region signature */
676 if (hndotp_otproff(oi, cc, OTP_HWSIGN_OFF) == OTP_SIGNATURE) {
677 oi->signvalid |= OTP_HW_REGION;
678 oi->boundary = hndotp_otproff(oi, cc, OTP_BOUNDARY_OFF);
681 if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE)
682 oi->signvalid |= OTP_SW_REGION;
684 if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE)
685 oi->signvalid |= OTP_CID_REGION;
687 /* Set OTP clkdiv for stability */
692 clkdiv = R_REG(osh, &cc->clkdiv);
694 (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT);
695 W_REG(osh, &cc->clkdiv, clkdiv);
703 si_setcoreidx(sih, idx);
708 static int hndotp_read_region(void *oh, int region, u16 *data, uint *wlen)
710 otpinfo_t *oi = (otpinfo_t *) oh;
715 /* Only support HW region (no active chips use HND OTP SW region) */
716 ASSERT(region == OTP_HW_REGION);
719 st = oi->hwprot | oi->signvalid;
720 if ((st & region) == 0)
721 return BCME_NOTFOUND;
724 ((int)*wlen < oi->boundary / 2) ? *wlen : (uint) oi->boundary / 2;
726 idx = si_coreidx(oi->sih);
727 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
730 for (i = 0; i < (int)*wlen; i++)
731 data[i] = hndotp_otpr(oh, cc, i);
733 si_setcoreidx(oi->sih, idx);
738 static int hndotp_nvread(void *oh, char *data, uint *len)
741 otpinfo_t *oi = (otpinfo_t *) oh;
742 u32 base, bound, lim = 0, st;
743 int i, chunk, gchunks, tsz = 0;
749 /* save the orig core */
750 idx = si_coreidx(oi->sih);
751 cc = si_setcoreidx(oi->sih, SI_CC_IDX);
754 st = hndotp_status(oh);
755 if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) {
760 /* Read the whole otp so we can easily manipulate it */
761 lim = hndotp_size(oh);
762 rawotp = kmalloc(lim, GFP_ATOMIC);
763 if (rawotp == NULL) {
767 for (i = 0; i < (int)(lim / 2); i++)
768 rawotp[i] = hndotp_otpr(oh, cc, i);
770 if ((st & OTP_HW_REGION) == 0) {
771 /* This could be a programming failure in the first
772 * chunk followed by one or more good chunks
774 for (i = 0; i < (int)(lim / 2); i++)
775 if (rawotp[i] == OTP_MAGIC)
778 if (i < (int)(lim / 2)) {
780 bound = (i * 2) + rawotp[i + 1];
786 bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF];
788 /* There are two cases: 1) The whole otp is used as nvram
789 * and 2) There is a hardware header followed by nvram.
791 if (rawotp[0] == OTP_MAGIC) {
797 /* Find and copy the data */
803 while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) {
804 int dsz, rsz = rawotp[i + 1];
806 if (((i * 2) + rsz) >= (int)lim) {
807 /* Bad length, try to find another chunk anyway */
810 if (hndcrc16((u8 *) &rawotp[i], rsz,
811 CRC16_INIT_VALUE) == CRC16_GOOD_VALUE) {
812 /* Good crc, copy the vars */
816 if (offset + dsz >= *len) {
819 bcopy((char *)&rawotp[i + 2], &data[offset], dsz);
821 /* Remove extra null characters at the end */
823 data[offset - 1] == 0 && data[offset - 2] == 0)
827 /* bad length or crc didn't check, try to find the next set */
828 if (rawotp[i + (rsz / 2)] == OTP_MAGIC) {
829 /* Assume length is good */
832 while (++i < (int)(lim / 2))
833 if (rawotp[i] == OTP_MAGIC)
845 si_setcoreidx(oi->sih, idx);
850 static otp_fn_t hndotp_fn = {
851 (otp_size_t) hndotp_size,
852 (otp_read_bit_t) hndotp_read_bit,
854 (otp_init_t) hndotp_init,
855 (otp_read_region_t) hndotp_read_region,
856 (otp_nvread_t) hndotp_nvread,
858 (otp_status_t) hndotp_status
861 #endif /* BCMHNDOTP */
864 * Common Code: Compiled for IPX / HND / AUTO
873 int otp_status(void *oh)
875 otpinfo_t *oi = (otpinfo_t *) oh;
877 return oi->fn->status(oh);
880 int otp_size(void *oh)
882 otpinfo_t *oi = (otpinfo_t *) oh;
884 return oi->fn->size(oh);
887 u16 otp_read_bit(void *oh, uint offset)
889 otpinfo_t *oi = (otpinfo_t *) oh;
890 uint idx = si_coreidx(oi->sih);
891 chipcregs_t *cc = si_setcoreidx(oi->sih, SI_CC_IDX);
892 u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
893 si_setcoreidx(oi->sih, idx);
897 void *otp_init(si_t *sih)
903 bzero(oi, sizeof(otpinfo_t));
905 oi->ccrev = sih->ccrev;
908 if (OTPTYPE_IPX(oi->ccrev))
913 if (OTPTYPE_HND(oi->ccrev))
917 if (oi->fn == NULL) {
922 oi->osh = si_osh(oi->sih);
924 ret = (oi->fn->init) (sih);
930 otp_read_region(si_t *sih, int region, u16 *data,
936 wasup = si_is_otp_powered(sih);
938 si_otp_power(sih, true);
940 if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
951 err = (((otpinfo_t *) oh)->fn->read_region) (oh, region, data, wlen);
955 si_otp_power(sih, false);
960 int otp_nvread(void *oh, char *data, uint *len)
962 otpinfo_t *oi = (otpinfo_t *) oh;
964 return oi->fn->nvread(oh, data, len);