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