Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
[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/kernel.h>
18 #include <linux/string.h>
19 #include <bcmdefs.h>
20 #include <osl.h>
21 #include <linuxver.h>
22 #include <bcmdevs.h>
23 #include <bcmutils.h>
24 #include <siutils.h>
25 #include <bcmendian.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         osl_t *osh;
81
82 #ifdef BCMIPXOTP
83         /* IPX OTP section */
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)
89                                  */
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 */
98
99 #ifdef BCMHNDOTP
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 */
106 } otpinfo_t;
107
108 static otpinfo_t otpinfo;
109
110 /*
111  * IPX OTP Code
112  *
113  *   Exported functions:
114  *      ipxotp_status()
115  *      ipxotp_size()
116  *      ipxotp_init()
117  *      ipxotp_read_bit()
118  *      ipxotp_read_region()
119  *      ipxotp_nvread()
120  *
121  */
122
123 #ifdef BCMIPXOTP
124
125 #define HWSW_RGN(rgn)           (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
126
127 /* OTP layout */
128 /* CC revs 21, 24 and 27 OTP General Use Region word offset */
129 #define REVA4_OTPGU_BASE        12
130
131 /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
132 #define REVB8_OTPGU_BASE        20
133
134 /* CC rev 36 OTP General Use Region word offset */
135 #define REV36_OTPGU_BASE        12
136
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
143
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)
152
153 /* OTP Size */
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 */
161
162 static int ipxotp_status(void *oh)
163 {
164         otpinfo_t *oi = (otpinfo_t *) oh;
165         return (int)(oi->status);
166 }
167
168 /* Return size in bytes */
169 static int ipxotp_size(void *oh)
170 {
171         otpinfo_t *oi = (otpinfo_t *) oh;
172         return (int)oi->wsize * 2;
173 }
174
175 static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
176 {
177         otpinfo_t *oi;
178
179         oi = (otpinfo_t *) oh;
180
181         ASSERT(wn < oi->wsize);
182         ASSERT(cc != NULL);
183
184         return R_REG(oi->osh, &cc->sromotp[wn]);
185 }
186
187 static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
188 {
189         otpinfo_t *oi = (otpinfo_t *) oh;
190         uint k, row, col;
191         u32 otpp, st;
192
193         row = off / oi->cols;
194         col = off % oi->cols;
195
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);
201
202         for (k = 0;
203              ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY)
204              && (k < OTPP_TRIES); k++)
205                 ;
206         if (k >= OTPP_TRIES) {
207                 return 0xffff;
208         }
209         if (st & OTPP_READERR) {
210                 return 0xffff;
211         }
212         st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
213
214         return (int)st;
215 }
216
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
219  */
220 static int ipxotp_max_rgnsz(si_t *sih, int osizew)
221 {
222         int ret = 0;
223
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;
228                 break;
229         case BCM4313_CHIP_ID:
230                 ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
231                 break;
232         default:
233                 ASSERT(0);      /* Don't konw about this chip */
234         }
235
236         return ret;
237 }
238
239 static void _ipxotp_init(otpinfo_t *oi, chipcregs_t *cc)
240 {
241         uint k;
242         u32 otpp, st;
243
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;
252                 else
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;
256         }
257
258         /* First issue an init command so the status is up to date */
259         otpp =
260             OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
261
262         W_REG(oi->osh, &cc->otpprog, otpp);
263         for (k = 0;
264              ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY)
265              && (k < OTPP_TRIES); k++)
266                 ;
267         if (k >= OTPP_TRIES) {
268                 return;
269         }
270
271         /* Read OTP lock bits and subregion programmed indication bits */
272         oi->status = R_REG(oi->osh, &cc->otpstatus);
273
274         if ((CHIPID(oi->sih->chip) == BCM43224_CHIP_ID)
275             || (CHIPID(oi->sih->chip) == BCM43225_CHIP_ID)) {
276                 u32 p_bits;
277                 p_bits =
278                     (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
279                      OTPGU_P_MSK)
280                     >> OTPGU_P_SHIFT;
281                 oi->status |= (p_bits << OTPS_GUP_SHIFT);
282         }
283
284         /*
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.
287          */
288         oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
289         oi->hwlim = oi->wsize;
290         if (oi->status & OTPS_GUP_HW) {
291                 oi->hwlim =
292                     ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
293                 oi->swbase = oi->hwlim;
294         } else
295                 oi->swbase = oi->hwbase;
296
297         /* subtract fuse and checksum from beginning */
298         oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
299
300         if (oi->status & OTPS_GUP_SW) {
301                 oi->swlim =
302                     ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
303                 oi->fbase = oi->swlim;
304         } else
305                 oi->fbase = oi->swbase;
306
307         oi->flim = oi->wsize;
308 }
309
310 static void *ipxotp_init(si_t *sih)
311 {
312         uint idx;
313         chipcregs_t *cc;
314         otpinfo_t *oi;
315
316         /* Make sure we're running IPX OTP */
317         ASSERT(OTPTYPE_IPX(sih->ccrev));
318         if (!OTPTYPE_IPX(sih->ccrev))
319                 return NULL;
320
321         /* Make sure OTP is not disabled */
322         if (si_is_otp_disabled(sih)) {
323                 return NULL;
324         }
325
326         /* Make sure OTP is powered up */
327         if (!si_is_otp_powered(sih)) {
328                 return NULL;
329         }
330
331         oi = &otpinfo;
332
333         /* Check for otp size */
334         switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
335         case 0:
336                 /* Nothing there */
337                 return NULL;
338         case 1:         /* 32x64 */
339                 oi->rows = 32;
340                 oi->cols = 64;
341                 oi->wsize = 128;
342                 break;
343         case 2:         /* 64x64 */
344                 oi->rows = 64;
345                 oi->cols = 64;
346                 oi->wsize = 256;
347                 break;
348         case 5:         /* 96x64 */
349                 oi->rows = 96;
350                 oi->cols = 64;
351                 oi->wsize = 384;
352                 break;
353         case 7:         /* 16x64 *//* 1024 bits */
354                 oi->rows = 16;
355                 oi->cols = 64;
356                 oi->wsize = 64;
357                 break;
358         default:
359                 /* Don't know the geometry */
360                 return NULL;
361         }
362
363         /* Retrieve OTP region info */
364         idx = si_coreidx(sih);
365         cc = si_setcoreidx(sih, SI_CC_IDX);
366         ASSERT(cc != NULL);
367
368         _ipxotp_init(oi, cc);
369
370         si_setcoreidx(sih, idx);
371
372         return (void *)oi;
373 }
374
375 static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
376 {
377         otpinfo_t *oi = (otpinfo_t *) oh;
378         uint idx;
379         chipcregs_t *cc;
380         uint base, i, sz;
381
382         /* Validate region selection */
383         switch (region) {
384         case OTP_HW_RGN:
385                 sz = (uint) oi->hwlim - oi->hwbase;
386                 if (!(oi->status & OTPS_GUP_HW)) {
387                         *wlen = sz;
388                         return BCME_NOTFOUND;
389                 }
390                 if (*wlen < sz) {
391                         *wlen = sz;
392                         return BCME_BUFTOOSHORT;
393                 }
394                 base = oi->hwbase;
395                 break;
396         case OTP_SW_RGN:
397                 sz = ((uint) oi->swlim - oi->swbase);
398                 if (!(oi->status & OTPS_GUP_SW)) {
399                         *wlen = sz;
400                         return BCME_NOTFOUND;
401                 }
402                 if (*wlen < sz) {
403                         *wlen = sz;
404                         return BCME_BUFTOOSHORT;
405                 }
406                 base = oi->swbase;
407                 break;
408         case OTP_CI_RGN:
409                 sz = OTPGU_CI_SZ;
410                 if (!(oi->status & OTPS_GUP_CI)) {
411                         *wlen = sz;
412                         return BCME_NOTFOUND;
413                 }
414                 if (*wlen < sz) {
415                         *wlen = sz;
416                         return BCME_BUFTOOSHORT;
417                 }
418                 base = oi->otpgu_base + OTPGU_CI_OFF;
419                 break;
420         case OTP_FUSE_RGN:
421                 sz = (uint) oi->flim - oi->fbase;
422                 if (!(oi->status & OTPS_GUP_FUSE)) {
423                         *wlen = sz;
424                         return BCME_NOTFOUND;
425                 }
426                 if (*wlen < sz) {
427                         *wlen = sz;
428                         return BCME_BUFTOOSHORT;
429                 }
430                 base = oi->fbase;
431                 break;
432         case OTP_ALL_RGN:
433                 sz = ((uint) oi->flim - oi->hwbase);
434                 if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
435                         *wlen = sz;
436                         return BCME_NOTFOUND;
437                 }
438                 if (*wlen < sz) {
439                         *wlen = sz;
440                         return BCME_BUFTOOSHORT;
441                 }
442                 base = oi->hwbase;
443                 break;
444         default:
445                 return BCME_BADARG;
446         }
447
448         idx = si_coreidx(oi->sih);
449         cc = si_setcoreidx(oi->sih, SI_CC_IDX);
450         ASSERT(cc != NULL);
451
452         /* Read the data */
453         for (i = 0; i < sz; i++)
454                 data[i] = ipxotp_otpr(oh, cc, base + i);
455
456         si_setcoreidx(oi->sih, idx);
457         *wlen = sz;
458         return 0;
459 }
460
461 static int ipxotp_nvread(void *oh, char *data, uint *len)
462 {
463         return BCME_UNSUPPORTED;
464 }
465
466 static otp_fn_t ipxotp_fn = {
467         (otp_size_t) ipxotp_size,
468         (otp_read_bit_t) ipxotp_read_bit,
469
470         (otp_init_t) ipxotp_init,
471         (otp_read_region_t) ipxotp_read_region,
472         (otp_nvread_t) ipxotp_nvread,
473
474         (otp_status_t) ipxotp_status
475 };
476
477 #endif                          /* BCMIPXOTP */
478
479 /*
480  * HND OTP Code
481  *
482  *   Exported functions:
483  *      hndotp_status()
484  *      hndotp_size()
485  *      hndotp_init()
486  *      hndotp_read_bit()
487  *      hndotp_read_region()
488  *      hndotp_nvread()
489  *
490  */
491
492 #ifdef BCMHNDOTP
493
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
502
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
510
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
515
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 */
530
531 #define OTP_HW_REGION   OTPS_HW_PROTECT
532 #define OTP_SW_REGION   OTPS_SW_PROTECT
533 #define OTP_CID_REGION  OTPS_CID_PROTECT
534
535 #if OTP_HW_REGION != OTP_HW_RGN
536 #error "incompatible OTP_HW_RGN"
537 #endif
538 #if OTP_SW_REGION != OTP_SW_RGN
539 #error "incompatible OTP_SW_RGN"
540 #endif
541 #if OTP_CID_REGION != OTP_CI_RGN
542 #error "incompatible OTP_CI_RGN"
543 #endif
544
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
552
553 #define OTP_WPR         4
554 #define OTP_SIGNATURE   0x578a
555 #define OTP_MAGIC       0x4e56
556
557 static int hndotp_status(void *oh)
558 {
559         otpinfo_t *oi = (otpinfo_t *) oh;
560         return (int)(oi->hwprot | oi->signvalid);
561 }
562
563 static int hndotp_size(void *oh)
564 {
565         otpinfo_t *oi = (otpinfo_t *) oh;
566         return (int)(oi->size);
567 }
568
569 static u16 hndotp_otpr(void *oh, chipcregs_t *cc, uint wn)
570 {
571         otpinfo_t *oi = (otpinfo_t *) oh;
572         osl_t *osh;
573         volatile u16 *ptr;
574
575         ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF));
576         ASSERT(cc != NULL);
577
578         osh = si_osh(oi->sih);
579
580         ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
581         return R_REG(osh, &ptr[wn]);
582 }
583
584 static u16 hndotp_otproff(void *oh, chipcregs_t *cc, int woff)
585 {
586         otpinfo_t *oi = (otpinfo_t *) oh;
587         osl_t *osh;
588         volatile u16 *ptr;
589
590         ASSERT(woff >= (-((int)oi->size / 2)));
591         ASSERT(woff < OTP_LIM_OFF);
592         ASSERT(cc != NULL);
593
594         osh = si_osh(oi->sih);
595
596         ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
597
598         return R_REG(osh, &ptr[(oi->size / 2) + woff]);
599 }
600
601 static u16 hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx)
602 {
603         otpinfo_t *oi = (otpinfo_t *) oh;
604         uint k, row, col;
605         u32 otpp, st;
606         osl_t *osh;
607
608         osh = si_osh(oi->sih);
609         row = idx / 65;
610         col = idx % 65;
611
612         otpp = OTPP_START_BUSY | OTPP_READ |
613             ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | (col & OTPP_COL_MASK);
614
615         W_REG(osh, &cc->otpprog, otpp);
616         st = R_REG(osh, &cc->otpprog);
617         for (k = 0;
618              ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES);
619              k++)
620                 st = R_REG(osh, &cc->otpprog);
621
622         if (k >= OTPP_TRIES) {
623                 return 0xffff;
624         }
625         if (st & OTPP_READERR) {
626                 return 0xffff;
627         }
628         st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
629         return (u16) st;
630 }
631
632 static void *hndotp_init(si_t *sih)
633 {
634         uint idx;
635         chipcregs_t *cc;
636         otpinfo_t *oi;
637         u32 cap = 0, clkdiv, otpdiv = 0;
638         void *ret = NULL;
639         osl_t *osh;
640
641         oi = &otpinfo;
642
643         idx = si_coreidx(sih);
644         osh = si_osh(oi->sih);
645
646         /* Check for otp */
647         cc = si_setcoreidx(sih, SI_CC_IDX);
648         if (cc != NULL) {
649                 cap = R_REG(osh, &cc->capabilities);
650                 if ((cap & CC_CAP_OTPSIZE) == 0) {
651                         /* Nothing there */
652                         goto out;
653                 }
654
655                 /* As of right now, support only 4320a2, 4311a1 and 4312 */
656                 ASSERT((oi->ccrev == 12) || (oi->ccrev == 17)
657                        || (oi->ccrev == 22));
658                 if (!
659                     ((oi->ccrev == 12) || (oi->ccrev == 17)
660                      || (oi->ccrev == 22)))
661                         return NULL;
662
663                 /* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is
664                  * 8 row (64 bytes) smaller
665                  */
666                 oi->size =
667                     1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT)
668                           + CC_CAP_OTPSIZE_BASE);
669                 if (oi->ccrev >= 18)
670                         oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2);
671
672                 oi->hwprot = (int)(R_REG(osh, &cc->otpstatus) & OTPS_PROTECT);
673                 oi->boundary = -1;
674
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);
679                 }
680
681                 if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE)
682                         oi->signvalid |= OTP_SW_REGION;
683
684                 if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE)
685                         oi->signvalid |= OTP_CID_REGION;
686
687                 /* Set OTP clkdiv for stability */
688                 if (oi->ccrev == 22)
689                         otpdiv = 12;
690
691                 if (otpdiv) {
692                         clkdiv = R_REG(osh, &cc->clkdiv);
693                         clkdiv =
694                             (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT);
695                         W_REG(osh, &cc->clkdiv, clkdiv);
696                 }
697                 udelay(10);
698
699                 ret = (void *)oi;
700         }
701
702  out:                           /* All done */
703         si_setcoreidx(sih, idx);
704
705         return ret;
706 }
707
708 static int hndotp_read_region(void *oh, int region, u16 *data, uint *wlen)
709 {
710         otpinfo_t *oi = (otpinfo_t *) oh;
711         u32 idx, st;
712         chipcregs_t *cc;
713         int i;
714
715         /* Only support HW region (no active chips use HND OTP SW region) */
716         ASSERT(region == OTP_HW_REGION);
717
718         /* Region empty? */
719         st = oi->hwprot | oi->signvalid;
720         if ((st & region) == 0)
721                 return BCME_NOTFOUND;
722
723         *wlen =
724             ((int)*wlen < oi->boundary / 2) ? *wlen : (uint) oi->boundary / 2;
725
726         idx = si_coreidx(oi->sih);
727         cc = si_setcoreidx(oi->sih, SI_CC_IDX);
728         ASSERT(cc != NULL);
729
730         for (i = 0; i < (int)*wlen; i++)
731                 data[i] = hndotp_otpr(oh, cc, i);
732
733         si_setcoreidx(oi->sih, idx);
734
735         return 0;
736 }
737
738 static int hndotp_nvread(void *oh, char *data, uint *len)
739 {
740         int rc = 0;
741         otpinfo_t *oi = (otpinfo_t *) oh;
742         u32 base, bound, lim = 0, st;
743         int i, chunk, gchunks, tsz = 0;
744         u32 idx;
745         chipcregs_t *cc;
746         uint offset;
747         u16 *rawotp = NULL;
748
749         /* save the orig core */
750         idx = si_coreidx(oi->sih);
751         cc = si_setcoreidx(oi->sih, SI_CC_IDX);
752         ASSERT(cc != NULL);
753
754         st = hndotp_status(oh);
755         if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) {
756                 rc = -1;
757                 goto out;
758         }
759
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) {
764                 rc = -2;
765                 goto out;
766         }
767         for (i = 0; i < (int)(lim / 2); i++)
768                 rawotp[i] = hndotp_otpr(oh, cc, i);
769
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
773                  */
774                 for (i = 0; i < (int)(lim / 2); i++)
775                         if (rawotp[i] == OTP_MAGIC)
776                                 break;
777
778                 if (i < (int)(lim / 2)) {
779                         base = i;
780                         bound = (i * 2) + rawotp[i + 1];
781                 } else {
782                         rc = -3;
783                         goto out;
784                 }
785         } else {
786                 bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF];
787
788                 /* There are two cases: 1) The whole otp is used as nvram
789                  * and 2) There is a hardware header followed by nvram.
790                  */
791                 if (rawotp[0] == OTP_MAGIC) {
792                         base = 0;
793                 } else
794                         base = bound;
795         }
796
797         /* Find and copy the data */
798
799         chunk = 0;
800         gchunks = 0;
801         i = base / 2;
802         offset = 0;
803         while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) {
804                 int dsz, rsz = rawotp[i + 1];
805
806                 if (((i * 2) + rsz) >= (int)lim) {
807                         /* Bad length, try to find another chunk anyway */
808                         rsz = 6;
809                 }
810                 if (hndcrc16((u8 *) &rawotp[i], rsz,
811                              CRC16_INIT_VALUE) == CRC16_GOOD_VALUE) {
812                         /* Good crc, copy the vars */
813                         gchunks++;
814                         dsz = rsz - 6;
815                         tsz += dsz;
816                         if (offset + dsz >= *len) {
817                                 goto out;
818                         }
819                         bcopy((char *)&rawotp[i + 2], &data[offset], dsz);
820                         offset += dsz;
821                         /* Remove extra null characters at the end */
822                         while (offset > 1 &&
823                                data[offset - 1] == 0 && data[offset - 2] == 0)
824                                 offset--;
825                         i += rsz / 2;
826                 } else {
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 */
830                                 i += rsz / 2;
831                         } else {
832                                 while (++i < (int)(lim / 2))
833                                         if (rawotp[i] == OTP_MAGIC)
834                                                 break;
835                         }
836                 }
837                 chunk++;
838         }
839
840         *len = offset;
841
842  out:
843         if (rawotp)
844                 kfree(rawotp);
845         si_setcoreidx(oi->sih, idx);
846
847         return rc;
848 }
849
850 static otp_fn_t hndotp_fn = {
851         (otp_size_t) hndotp_size,
852         (otp_read_bit_t) hndotp_read_bit,
853
854         (otp_init_t) hndotp_init,
855         (otp_read_region_t) hndotp_read_region,
856         (otp_nvread_t) hndotp_nvread,
857
858         (otp_status_t) hndotp_status
859 };
860
861 #endif                          /* BCMHNDOTP */
862
863 /*
864  * Common Code: Compiled for IPX / HND / AUTO
865  *      otp_status()
866  *      otp_size()
867  *      otp_read_bit()
868  *      otp_init()
869  *      otp_read_region()
870  *      otp_nvread()
871  */
872
873 int otp_status(void *oh)
874 {
875         otpinfo_t *oi = (otpinfo_t *) oh;
876
877         return oi->fn->status(oh);
878 }
879
880 int otp_size(void *oh)
881 {
882         otpinfo_t *oi = (otpinfo_t *) oh;
883
884         return oi->fn->size(oh);
885 }
886
887 u16 otp_read_bit(void *oh, uint offset)
888 {
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);
894         return readBit;
895 }
896
897 void *otp_init(si_t *sih)
898 {
899         otpinfo_t *oi;
900         void *ret = NULL;
901
902         oi = &otpinfo;
903         bzero(oi, sizeof(otpinfo_t));
904
905         oi->ccrev = sih->ccrev;
906
907 #ifdef BCMIPXOTP
908         if (OTPTYPE_IPX(oi->ccrev))
909                 oi->fn = &ipxotp_fn;
910 #endif
911
912 #ifdef BCMHNDOTP
913         if (OTPTYPE_HND(oi->ccrev))
914                 oi->fn = &hndotp_fn;
915 #endif
916
917         if (oi->fn == NULL) {
918                 return NULL;
919         }
920
921         oi->sih = sih;
922         oi->osh = si_osh(oi->sih);
923
924         ret = (oi->fn->init) (sih);
925
926         return ret;
927 }
928
929 int
930 otp_read_region(si_t *sih, int region, u16 *data,
931                                  uint *wlen) {
932         bool wasup = false;
933         void *oh;
934         int err = 0;
935
936         wasup = si_is_otp_powered(sih);
937         if (!wasup)
938                 si_otp_power(sih, true);
939
940         if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) {
941                 err = BCME_NOTREADY;
942                 goto out;
943         }
944
945         oh = otp_init(sih);
946         if (oh == NULL) {
947                 err = BCME_ERROR;
948                 goto out;
949         }
950
951         err = (((otpinfo_t *) oh)->fn->read_region) (oh, region, data, wlen);
952
953  out:
954         if (!wasup)
955                 si_otp_power(sih, false);
956
957         return err;
958 }
959
960 int otp_nvread(void *oh, char *data, uint *len)
961 {
962         otpinfo_t *oi = (otpinfo_t *) oh;
963
964         return oi->fn->nvread(oh, data, len);
965 }