17991212a22d7a6ed73ae1ad7e8368a4a6ceb1f0
[pandora-kernel.git] / drivers / staging / brcm80211 / util / bcmotp.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
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.
7  *
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.
15  */
16
17 #include <linux/delay.h>
18 #include <linux/kernel.h>
19 #include <linux/string.h>
20 #include <bcmdefs.h>
21 #include <linux/module.h>
22 #include <linux/pci.h>
23 #include <bcmdevs.h>
24 #include <bcmutils.h>
25 #include <siutils.h>
26 #include <hndsoc.h>
27 #include <sbchipc.h>
28 #include <bcmotp.h>
29 #include "siutils_priv.h"
30
31 /*
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
35  *
36  * Define BCMHNDOTP to include support for the HND OTP controller.
37  * Define BCMIPXOTP to include support for the IPX OTP controller.
38  *
39  * NOTE 1: More than one may be defined
40  * NOTE 2: If none are defined, the default is to include them all.
41  */
42
43 #if !defined(BCMHNDOTP) && !defined(BCMIPXOTP)
44 #define BCMHNDOTP       1
45 #define BCMIPXOTP       1
46 #endif
47
48 #define OTPTYPE_HND(ccrev)      ((ccrev) < 21 || (ccrev) == 22)
49 #define OTPTYPE_IPX(ccrev)      ((ccrev) == 21 || (ccrev) >= 23)
50
51 #define OTPP_TRIES      10000000        /* # of tries for OTPP */
52
53 #ifdef BCMIPXOTP
54 #define MAXNUMRDES              9       /* Maximum OTP redundancy entries */
55 #endif
56
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,
63                                   uint *wlen);
64 typedef int (*otp_nvread_t) (void *oh, char *data, uint *len);
65
66 /* OTP function struct */
67 typedef struct otp_fn_s {
68         otp_size_t size;
69         otp_read_bit_t read_bit;
70         otp_init_t init;
71         otp_read_region_t read_region;
72         otp_nvread_t nvread;
73         otp_status_t status;
74 } otp_fn_t;
75
76 typedef struct {
77         uint ccrev;             /* chipc revision */
78         otp_fn_t *fn;           /* OTP functions */
79         si_t *sih;              /* Saved sb handle */
80
81 #ifdef BCMIPXOTP
82         /* IPX OTP section */
83         u16 wsize;              /* Size of otp in words */
84         u16 rows;               /* Geometry */
85         u16 cols;               /* Geometry */
86         u32 status;             /* Flag bits (lock/prog/rv).
87                                  * (Reflected only when OTP is power cycled)
88                                  */
89         u16 hwbase;             /* hardware subregion offset */
90         u16 hwlim;              /* hardware subregion boundary */
91         u16 swbase;             /* software subregion offset */
92         u16 swlim;              /* software subregion boundary */
93         u16 fbase;              /* fuse subregion offset */
94         u16 flim;               /* fuse subregion boundary */
95         int otpgu_base;         /* offset to General Use Region */
96 #endif                          /* BCMIPXOTP */
97
98 #ifdef BCMHNDOTP
99         /* HND OTP section */
100         uint size;              /* Size of otp in bytes */
101         uint hwprot;            /* Hardware protection bits */
102         uint signvalid;         /* Signature valid bits */
103         int boundary;           /* hw/sw boundary */
104 #endif                          /* BCMHNDOTP */
105 } otpinfo_t;
106
107 static otpinfo_t otpinfo;
108
109 /*
110  * IPX OTP Code
111  *
112  *   Exported functions:
113  *      ipxotp_status()
114  *      ipxotp_size()
115  *      ipxotp_init()
116  *      ipxotp_read_bit()
117  *      ipxotp_read_region()
118  *      ipxotp_nvread()
119  *
120  */
121
122 #ifdef BCMIPXOTP
123
124 #define HWSW_RGN(rgn)           (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
125
126 /* OTP layout */
127 /* CC revs 21, 24 and 27 OTP General Use Region word offset */
128 #define REVA4_OTPGU_BASE        12
129
130 /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
131 #define REVB8_OTPGU_BASE        20
132
133 /* CC rev 36 OTP General Use Region word offset */
134 #define REV36_OTPGU_BASE        12
135
136 /* Subregion word offsets in General Use region */
137 #define OTPGU_HSB_OFF           0
138 #define OTPGU_SFB_OFF           1
139 #define OTPGU_CI_OFF            2
140 #define OTPGU_P_OFF             3
141 #define OTPGU_SROM_OFF          4
142
143 /* Flag bit offsets in General Use region  */
144 #define OTPGU_HWP_OFF           60
145 #define OTPGU_SWP_OFF           61
146 #define OTPGU_CIP_OFF           62
147 #define OTPGU_FUSEP_OFF         63
148 #define OTPGU_CIP_MSK           0x4000
149 #define OTPGU_P_MSK             0xf000
150 #define OTPGU_P_SHIFT           (OTPGU_HWP_OFF % 16)
151
152 /* OTP Size */
153 #define OTP_SZ_FU_324           ((roundup(324, 8))/8)   /* 324 bits */
154 #define OTP_SZ_FU_288           (288/8) /* 288 bits */
155 #define OTP_SZ_FU_216           (216/8) /* 216 bits */
156 #define OTP_SZ_FU_72            (72/8)  /* 72 bits */
157 #define OTP_SZ_CHECKSUM         (16/8)  /* 16 bits */
158 #define OTP4315_SWREG_SZ        178     /* 178 bytes */
159 #define OTP_SZ_FU_144           (144/8) /* 144 bits */
160
161 static int ipxotp_status(void *oh)
162 {
163         otpinfo_t *oi = (otpinfo_t *) oh;
164         return (int)(oi->status);
165 }
166
167 /* Return size in bytes */
168 static int ipxotp_size(void *oh)
169 {
170         otpinfo_t *oi = (otpinfo_t *) oh;
171         return (int)oi->wsize * 2;
172 }
173
174 static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
175 {
176         otpinfo_t *oi;
177
178         oi = (otpinfo_t *) oh;
179
180         ASSERT(wn < oi->wsize);
181         ASSERT(cc != NULL);
182
183         return R_REG(&cc->sromotp[wn]);
184 }
185
186 static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
187 {
188         otpinfo_t *oi = (otpinfo_t *) oh;
189         uint k, row, col;
190         u32 otpp, st;
191
192         row = off / oi->cols;
193         col = off % oi->cols;
194
195         otpp = OTPP_START_BUSY |
196             ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
197             ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
198             ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
199         W_REG(&cc->otpprog, otpp);
200
201         for (k = 0;
202              ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
203              && (k < OTPP_TRIES); k++)
204                 ;
205         if (k >= OTPP_TRIES) {
206                 return 0xffff;
207         }
208         if (st & OTPP_READERR) {
209                 return 0xffff;
210         }
211         st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
212
213         return (int)st;
214 }
215
216 /* Calculate max HW/SW region byte size by subtracting fuse region and checksum size,
217  * osizew is oi->wsize (OTP size - GU size) in words
218  */
219 static int ipxotp_max_rgnsz(si_t *sih, int osizew)
220 {
221         int ret = 0;
222
223         switch (sih->chip) {
224         case BCM43224_CHIP_ID:
225         case BCM43225_CHIP_ID:
226                 ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
227                 break;
228         case BCM4313_CHIP_ID:
229                 ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
230                 break;
231         default:
232                 ASSERT(0);      /* Don't know about this chip */
233         }
234
235         return ret;
236 }
237
238 static void _ipxotp_init(otpinfo_t *oi, chipcregs_t *cc)
239 {
240         uint k;
241         u32 otpp, st;
242
243         /* record word offset of General Use Region for various chipcommon revs */
244         if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
245             || oi->sih->ccrev == 27) {
246                 oi->otpgu_base = REVA4_OTPGU_BASE;
247         } else if (oi->sih->ccrev == 36) {
248                 /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
249                 if (oi->wsize >= 128)
250                         oi->otpgu_base = REVB8_OTPGU_BASE;
251                 else
252                         oi->otpgu_base = REV36_OTPGU_BASE;
253         } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
254                 oi->otpgu_base = REVB8_OTPGU_BASE;
255         }
256
257         /* First issue an init command so the status is up to date */
258         otpp =
259             OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
260
261         W_REG(&cc->otpprog, otpp);
262         for (k = 0;
263              ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
264              && (k < OTPP_TRIES); k++)
265                 ;
266         if (k >= OTPP_TRIES) {
267                 return;
268         }
269
270         /* Read OTP lock bits and subregion programmed indication bits */
271         oi->status = R_REG(&cc->otpstatus);
272
273         if ((oi->sih->chip == BCM43224_CHIP_ID)
274             || (oi->sih->chip == BCM43225_CHIP_ID)) {
275                 u32 p_bits;
276                 p_bits =
277                     (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
278                      OTPGU_P_MSK)
279                     >> OTPGU_P_SHIFT;
280                 oi->status |= (p_bits << OTPS_GUP_SHIFT);
281         }
282
283         /*
284          * h/w region base and fuse region limit are fixed to the top and
285          * the bottom of the general use region. Everything else can be flexible.
286          */
287         oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
288         oi->hwlim = oi->wsize;
289         if (oi->status & OTPS_GUP_HW) {
290                 oi->hwlim =
291                     ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
292                 oi->swbase = oi->hwlim;
293         } else
294                 oi->swbase = oi->hwbase;
295
296         /* subtract fuse and checksum from beginning */
297         oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
298
299         if (oi->status & OTPS_GUP_SW) {
300                 oi->swlim =
301                     ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
302                 oi->fbase = oi->swlim;
303         } else
304                 oi->fbase = oi->swbase;
305
306         oi->flim = oi->wsize;
307 }
308
309 static void *ipxotp_init(si_t *sih)
310 {
311         uint idx;
312         chipcregs_t *cc;
313         otpinfo_t *oi;
314
315         /* Make sure we're running IPX OTP */
316         ASSERT(OTPTYPE_IPX(sih->ccrev));
317         if (!OTPTYPE_IPX(sih->ccrev))
318                 return NULL;
319
320         /* Make sure OTP is not disabled */
321         if (si_is_otp_disabled(sih)) {
322                 return NULL;
323         }
324
325         /* Make sure OTP is powered up */
326         if (!si_is_otp_powered(sih)) {
327                 return NULL;
328         }
329
330         oi = &otpinfo;
331
332         /* Check for otp size */
333         switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
334         case 0:
335                 /* Nothing there */
336                 return NULL;
337         case 1:         /* 32x64 */
338                 oi->rows = 32;
339                 oi->cols = 64;
340                 oi->wsize = 128;
341                 break;
342         case 2:         /* 64x64 */
343                 oi->rows = 64;
344                 oi->cols = 64;
345                 oi->wsize = 256;
346                 break;
347         case 5:         /* 96x64 */
348                 oi->rows = 96;
349                 oi->cols = 64;
350                 oi->wsize = 384;
351                 break;
352         case 7:         /* 16x64 *//* 1024 bits */
353                 oi->rows = 16;
354                 oi->cols = 64;
355                 oi->wsize = 64;
356                 break;
357         default:
358                 /* Don't know the geometry */
359                 return NULL;
360         }
361
362         /* Retrieve OTP region info */
363         idx = si_coreidx(sih);
364         cc = si_setcoreidx(sih, SI_CC_IDX);
365         ASSERT(cc != NULL);
366
367         _ipxotp_init(oi, cc);
368
369         si_setcoreidx(sih, idx);
370
371         return (void *)oi;
372 }
373
374 static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
375 {
376         otpinfo_t *oi = (otpinfo_t *) oh;
377         uint idx;
378         chipcregs_t *cc;
379         uint base, i, sz;
380
381         /* Validate region selection */
382         switch (region) {
383         case OTP_HW_RGN:
384                 sz = (uint) oi->hwlim - oi->hwbase;
385                 if (!(oi->status & OTPS_GUP_HW)) {
386                         *wlen = sz;
387                         return BCME_NOTFOUND;
388                 }
389                 if (*wlen < sz) {
390                         *wlen = sz;
391                         return BCME_BUFTOOSHORT;
392                 }
393                 base = oi->hwbase;
394                 break;
395         case OTP_SW_RGN:
396                 sz = ((uint) oi->swlim - oi->swbase);
397                 if (!(oi->status & OTPS_GUP_SW)) {
398                         *wlen = sz;
399                         return BCME_NOTFOUND;
400                 }
401                 if (*wlen < sz) {
402                         *wlen = sz;
403                         return BCME_BUFTOOSHORT;
404                 }
405                 base = oi->swbase;
406                 break;
407         case OTP_CI_RGN:
408                 sz = OTPGU_CI_SZ;
409                 if (!(oi->status & OTPS_GUP_CI)) {
410                         *wlen = sz;
411                         return BCME_NOTFOUND;
412                 }
413                 if (*wlen < sz) {
414                         *wlen = sz;
415                         return BCME_BUFTOOSHORT;
416                 }
417                 base = oi->otpgu_base + OTPGU_CI_OFF;
418                 break;
419         case OTP_FUSE_RGN:
420                 sz = (uint) oi->flim - oi->fbase;
421                 if (!(oi->status & OTPS_GUP_FUSE)) {
422                         *wlen = sz;
423                         return BCME_NOTFOUND;
424                 }
425                 if (*wlen < sz) {
426                         *wlen = sz;
427                         return BCME_BUFTOOSHORT;
428                 }
429                 base = oi->fbase;
430                 break;
431         case OTP_ALL_RGN:
432                 sz = ((uint) oi->flim - oi->hwbase);
433                 if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
434                         *wlen = sz;
435                         return BCME_NOTFOUND;
436                 }
437                 if (*wlen < sz) {
438                         *wlen = sz;
439                         return BCME_BUFTOOSHORT;
440                 }
441                 base = oi->hwbase;
442                 break;
443         default:
444                 return BCME_BADARG;
445         }
446
447         idx = si_coreidx(oi->sih);
448         cc = si_setcoreidx(oi->sih, SI_CC_IDX);
449         ASSERT(cc != NULL);
450
451         /* Read the data */
452         for (i = 0; i < sz; i++)
453                 data[i] = ipxotp_otpr(oh, cc, base + i);
454
455         si_setcoreidx(oi->sih, idx);
456         *wlen = sz;
457         return 0;
458 }
459
460 static int ipxotp_nvread(void *oh, char *data, uint *len)
461 {
462         return BCME_UNSUPPORTED;
463 }
464
465 static otp_fn_t ipxotp_fn = {
466         (otp_size_t) ipxotp_size,
467         (otp_read_bit_t) ipxotp_read_bit,
468
469         (otp_init_t) ipxotp_init,
470         (otp_read_region_t) ipxotp_read_region,
471         (otp_nvread_t) ipxotp_nvread,
472
473         (otp_status_t) ipxotp_status
474 };
475
476 #endif                          /* BCMIPXOTP */
477
478 /*
479  * HND OTP Code
480  *
481  *   Exported functions:
482  *      hndotp_status()
483  *      hndotp_size()
484  *      hndotp_init()
485  *      hndotp_read_bit()
486  *      hndotp_read_region()
487  *      hndotp_nvread()
488  *
489  */
490
491 #ifdef BCMHNDOTP
492
493 /* Fields in otpstatus */
494 #define OTPS_PROGFAIL           0x80000000
495 #define OTPS_PROTECT            0x00000007
496 #define OTPS_HW_PROTECT         0x00000001
497 #define OTPS_SW_PROTECT         0x00000002
498 #define OTPS_CID_PROTECT        0x00000004
499 #define OTPS_RCEV_MSK           0x00003f00
500 #define OTPS_RCEV_SHIFT         8
501
502 /* Fields in the otpcontrol register */
503 #define OTPC_RECWAIT            0xff000000
504 #define OTPC_PROGWAIT           0x00ffff00
505 #define OTPC_PRW_SHIFT          8
506 #define OTPC_MAXFAIL            0x00000038
507 #define OTPC_VSEL               0x00000006
508 #define OTPC_SELVL              0x00000001
509
510 /* OTP regions (Word offsets from otp size) */
511 #define OTP_SWLIM_OFF   (-4)
512 #define OTP_CIDBASE_OFF 0
513 #define OTP_CIDLIM_OFF  4
514
515 /* Predefined OTP words (Word offset from otp size) */
516 #define OTP_BOUNDARY_OFF (-4)
517 #define OTP_HWSIGN_OFF  (-3)
518 #define OTP_SWSIGN_OFF  (-2)
519 #define OTP_CIDSIGN_OFF (-1)
520 #define OTP_CID_OFF     0
521 #define OTP_PKG_OFF     1
522 #define OTP_FID_OFF     2
523 #define OTP_RSV_OFF     3
524 #define OTP_LIM_OFF     4
525 #define OTP_RD_OFF      4       /* Redundancy row starts here */
526 #define OTP_RC0_OFF     28      /* Redundancy control word 1 */
527 #define OTP_RC1_OFF     32      /* Redundancy control word 2 */
528 #define OTP_RC_LIM_OFF  36      /* Redundancy control word end */
529
530 #define OTP_HW_REGION   OTPS_HW_PROTECT
531 #define OTP_SW_REGION   OTPS_SW_PROTECT
532 #define OTP_CID_REGION  OTPS_CID_PROTECT
533
534 #if OTP_HW_REGION != OTP_HW_RGN
535 #error "incompatible OTP_HW_RGN"
536 #endif
537 #if OTP_SW_REGION != OTP_SW_RGN
538 #error "incompatible OTP_SW_RGN"
539 #endif
540 #if OTP_CID_REGION != OTP_CI_RGN
541 #error "incompatible OTP_CI_RGN"
542 #endif
543
544 /* Redundancy entry definitions */
545 #define OTP_RCE_ROW_SZ          6
546 #define OTP_RCE_SIGN_MASK       0x7fff
547 #define OTP_RCE_ROW_MASK        0x3f
548 #define OTP_RCE_BITS            21
549 #define OTP_RCE_SIGN_SZ         15
550 #define OTP_RCE_BIT0            1
551
552 #define OTP_WPR         4
553 #define OTP_SIGNATURE   0x578a
554 #define OTP_MAGIC       0x4e56
555
556 static int hndotp_status(void *oh)
557 {
558         otpinfo_t *oi = (otpinfo_t *) oh;
559         return (int)(oi->hwprot | oi->signvalid);
560 }
561
562 static int hndotp_size(void *oh)
563 {
564         otpinfo_t *oi = (otpinfo_t *) oh;
565         return (int)(oi->size);
566 }
567
568 static u16 hndotp_otpr(void *oh, chipcregs_t *cc, uint wn)
569 {
570 #ifdef BCMDBG
571         otpinfo_t *oi = (otpinfo_t *) oh;
572 #endif
573         volatile u16 *ptr;
574
575         ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF));
576         ASSERT(cc != NULL);
577
578         ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
579         return R_REG(&ptr[wn]);
580 }
581
582 static u16 hndotp_otproff(void *oh, chipcregs_t *cc, int woff)
583 {
584         otpinfo_t *oi = (otpinfo_t *) oh;
585         volatile u16 *ptr;
586
587         ASSERT(woff >= (-((int)oi->size / 2)));
588         ASSERT(woff < OTP_LIM_OFF);
589         ASSERT(cc != NULL);
590
591         ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
592
593         return R_REG(&ptr[(oi->size / 2) + woff]);
594 }
595
596 static u16 hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx)
597 {
598         uint k, row, col;
599         u32 otpp, st;
600
601         row = idx / 65;
602         col = idx % 65;
603
604         otpp = OTPP_START_BUSY | OTPP_READ |
605             ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | (col & OTPP_COL_MASK);
606
607         W_REG(&cc->otpprog, otpp);
608         st = R_REG(&cc->otpprog);
609         for (k = 0;
610              ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES);
611              k++)
612                 st = R_REG(&cc->otpprog);
613
614         if (k >= OTPP_TRIES) {
615                 return 0xffff;
616         }
617         if (st & OTPP_READERR) {
618                 return 0xffff;
619         }
620         st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
621         return (u16) st;
622 }
623
624 static void *hndotp_init(si_t *sih)
625 {
626         uint idx;
627         chipcregs_t *cc;
628         otpinfo_t *oi;
629         u32 cap = 0, clkdiv, otpdiv = 0;
630         void *ret = NULL;
631
632         oi = &otpinfo;
633
634         idx = si_coreidx(sih);
635
636         /* Check for otp */
637         cc = si_setcoreidx(sih, SI_CC_IDX);
638         if (cc != NULL) {
639                 cap = R_REG(&cc->capabilities);
640                 if ((cap & CC_CAP_OTPSIZE) == 0) {
641                         /* Nothing there */
642                         goto out;
643                 }
644
645                 /* As of right now, support only 4320a2, 4311a1 and 4312 */
646                 ASSERT((oi->ccrev == 12) || (oi->ccrev == 17)
647                        || (oi->ccrev == 22));
648                 if (!
649                     ((oi->ccrev == 12) || (oi->ccrev == 17)
650                      || (oi->ccrev == 22)))
651                         return NULL;
652
653                 /* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is
654                  * 8 row (64 bytes) smaller
655                  */
656                 oi->size =
657                     1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT)
658                           + CC_CAP_OTPSIZE_BASE);
659                 if (oi->ccrev >= 18)
660                         oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2);
661
662                 oi->hwprot = (int)(R_REG(&cc->otpstatus) & OTPS_PROTECT);
663                 oi->boundary = -1;
664
665                 /* Check the region signature */
666                 if (hndotp_otproff(oi, cc, OTP_HWSIGN_OFF) == OTP_SIGNATURE) {
667                         oi->signvalid |= OTP_HW_REGION;
668                         oi->boundary = hndotp_otproff(oi, cc, OTP_BOUNDARY_OFF);
669                 }
670
671                 if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE)
672                         oi->signvalid |= OTP_SW_REGION;
673
674                 if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE)
675                         oi->signvalid |= OTP_CID_REGION;
676
677                 /* Set OTP clkdiv for stability */
678                 if (oi->ccrev == 22)
679                         otpdiv = 12;
680
681                 if (otpdiv) {
682                         clkdiv = R_REG(&cc->clkdiv);
683                         clkdiv =
684                             (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT);
685                         W_REG(&cc->clkdiv, clkdiv);
686                 }
687                 udelay(10);
688
689                 ret = (void *)oi;
690         }
691
692  out:                           /* All done */
693         si_setcoreidx(sih, idx);
694
695         return ret;
696 }
697
698 static int hndotp_read_region(void *oh, int region, u16 *data, uint *wlen)
699 {
700         otpinfo_t *oi = (otpinfo_t *) oh;
701         u32 idx, st;
702         chipcregs_t *cc;
703         int i;
704
705         /* Only support HW region (no active chips use HND OTP SW region) */
706         ASSERT(region == OTP_HW_REGION);
707
708         /* Region empty? */
709         st = oi->hwprot | oi->signvalid;
710         if ((st & region) == 0)
711                 return BCME_NOTFOUND;
712
713         *wlen =
714             ((int)*wlen < oi->boundary / 2) ? *wlen : (uint) oi->boundary / 2;
715
716         idx = si_coreidx(oi->sih);
717         cc = si_setcoreidx(oi->sih, SI_CC_IDX);
718         ASSERT(cc != NULL);
719
720         for (i = 0; i < (int)*wlen; i++)
721                 data[i] = hndotp_otpr(oh, cc, i);
722
723         si_setcoreidx(oi->sih, idx);
724
725         return 0;
726 }
727
728 static int hndotp_nvread(void *oh, char *data, uint *len)
729 {
730         int rc = 0;
731         otpinfo_t *oi = (otpinfo_t *) oh;
732         u32 base, bound, lim = 0, st;
733         int i, chunk, gchunks, tsz = 0;
734         u32 idx;
735         chipcregs_t *cc;
736         uint offset;
737         u16 *rawotp = NULL;
738
739         /* save the orig core */
740         idx = si_coreidx(oi->sih);
741         cc = si_setcoreidx(oi->sih, SI_CC_IDX);
742         ASSERT(cc != NULL);
743
744         st = hndotp_status(oh);
745         if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) {
746                 rc = -1;
747                 goto out;
748         }
749
750         /* Read the whole otp so we can easily manipulate it */
751         lim = hndotp_size(oh);
752         rawotp = kmalloc(lim, GFP_ATOMIC);
753         if (rawotp == NULL) {
754                 rc = -2;
755                 goto out;
756         }
757         for (i = 0; i < (int)(lim / 2); i++)
758                 rawotp[i] = hndotp_otpr(oh, cc, i);
759
760         if ((st & OTP_HW_REGION) == 0) {
761                 /* This could be a programming failure in the first
762                  * chunk followed by one or more good chunks
763                  */
764                 for (i = 0; i < (int)(lim / 2); i++)
765                         if (rawotp[i] == OTP_MAGIC)
766                                 break;
767
768                 if (i < (int)(lim / 2)) {
769                         base = i;
770                         bound = (i * 2) + rawotp[i + 1];
771                 } else {
772                         rc = -3;
773                         goto out;
774                 }
775         } else {
776                 bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF];
777
778                 /* There are two cases: 1) The whole otp is used as nvram
779                  * and 2) There is a hardware header followed by nvram.
780                  */
781                 if (rawotp[0] == OTP_MAGIC) {
782                         base = 0;
783                 } else
784                         base = bound;
785         }
786
787         /* Find and copy the data */
788
789         chunk = 0;
790         gchunks = 0;
791         i = base / 2;
792         offset = 0;
793         while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) {
794                 int dsz, rsz = rawotp[i + 1];
795
796                 if (((i * 2) + rsz) >= (int)lim) {
797                         /* Bad length, try to find another chunk anyway */
798                         rsz = 6;
799                 }
800                 if (hndcrc16((u8 *) &rawotp[i], rsz,
801                              CRC16_INIT_VALUE) == CRC16_GOOD_VALUE) {
802                         /* Good crc, copy the vars */
803                         gchunks++;
804                         dsz = rsz - 6;
805                         tsz += dsz;
806                         if (offset + dsz >= *len) {
807                                 goto out;
808                         }
809                         memcpy(&data[offset], &rawotp[i + 2], dsz);
810                         offset += dsz;
811                         /* Remove extra null characters at the end */
812                         while (offset > 1 &&
813                                data[offset - 1] == 0 && data[offset - 2] == 0)
814                                 offset--;
815                         i += rsz / 2;
816                 } else {
817                         /* bad length or crc didn't check, try to find the next set */
818                         if (rawotp[i + (rsz / 2)] == OTP_MAGIC) {
819                                 /* Assume length is good */
820                                 i += rsz / 2;
821                         } else {
822                                 while (++i < (int)(lim / 2))
823                                         if (rawotp[i] == OTP_MAGIC)
824                                                 break;
825                         }
826                 }
827                 chunk++;
828         }
829
830         *len = offset;
831
832  out:
833         kfree(rawotp);
834         si_setcoreidx(oi->sih, idx);
835
836         return rc;
837 }
838
839 static otp_fn_t hndotp_fn = {
840         (otp_size_t) hndotp_size,
841         (otp_read_bit_t) hndotp_read_bit,
842
843         (otp_init_t) hndotp_init,
844         (otp_read_region_t) hndotp_read_region,
845         (otp_nvread_t) hndotp_nvread,
846
847         (otp_status_t) hndotp_status
848 };
849
850 #endif                          /* BCMHNDOTP */
851
852 /*
853  * Common Code: Compiled for IPX / HND / AUTO
854  *      otp_status()
855  *      otp_size()
856  *      otp_read_bit()
857  *      otp_init()
858  *      otp_read_region()
859  *      otp_nvread()
860  */
861
862 int otp_status(void *oh)
863 {
864         otpinfo_t *oi = (otpinfo_t *) oh;
865
866         return oi->fn->status(oh);
867 }
868
869 int otp_size(void *oh)
870 {
871         otpinfo_t *oi = (otpinfo_t *) oh;
872
873         return oi->fn->size(oh);
874 }
875
876 u16 otp_read_bit(void *oh, uint offset)
877 {
878         otpinfo_t *oi = (otpinfo_t *) oh;
879         uint idx = si_coreidx(oi->sih);
880         chipcregs_t *cc = si_setcoreidx(oi->sih, SI_CC_IDX);
881         u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
882         si_setcoreidx(oi->sih, idx);
883         return readBit;
884 }
885
886 void *otp_init(si_t *sih)
887 {
888         otpinfo_t *oi;
889         void *ret = NULL;
890
891         oi = &otpinfo;
892         memset(oi, 0, sizeof(otpinfo_t));
893
894         oi->ccrev = sih->ccrev;
895
896 #ifdef BCMIPXOTP
897         if (OTPTYPE_IPX(oi->ccrev))
898                 oi->fn = &ipxotp_fn;
899 #endif
900
901 #ifdef BCMHNDOTP
902         if (OTPTYPE_HND(oi->ccrev))
903                 oi->fn = &hndotp_fn;
904 #endif
905
906         if (oi->fn == NULL) {
907                 return NULL;
908         }
909
910         oi->sih = sih;
911
912         ret = (oi->fn->init) (sih);
913
914         return ret;
915 }
916
917 int
918 otp_read_region(si_t *sih, int region, u16 *data,
919                                  uint *wlen) {
920         bool wasup = false;
921         void *oh;
922         int err = 0;
923
924         wasup = si_is_otp_powered(sih);
925         if (!wasup)
926                 si_otp_power(sih, true);
927
928         if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
929                 err = BCME_NOTREADY;
930                 goto out;
931         }
932
933         oh = otp_init(sih);
934         if (oh == NULL) {
935                 err = BCME_ERROR;
936                 goto out;
937         }
938
939         err = (((otpinfo_t *) oh)->fn->read_region) (oh, region, data, wlen);
940
941  out:
942         if (!wasup)
943                 si_otp_power(sih, false);
944
945         return err;
946 }
947
948 int otp_nvread(void *oh, char *data, uint *len)
949 {
950         otpinfo_t *oi = (otpinfo_t *) oh;
951
952         return oi->fn->nvread(oh, data, len);
953 }