]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/brcm80211/util/bcmotp.c
Fix common misspellings
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / brcm80211 / util / bcmotp.c
CommitLineData
a9533e7e
HP
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
01d11441 17#include <linux/delay.h>
3327989a
BR
18#include <linux/kernel.h>
19#include <linux/string.h>
a1c16ed2 20#include <bcmdefs.h>
c6ac24e9
BR
21#include <linux/module.h>
22#include <linux/pci.h>
a9533e7e
HP
23#include <bcmdevs.h>
24#include <bcmutils.h>
25#include <siutils.h>
a9533e7e
HP
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 */
58typedef int (*otp_status_t) (void *oh);
59typedef int (*otp_size_t) (void *oh);
7cc4a4c0 60typedef void *(*otp_init_t) (si_t *sih);
7d4df48e
GKH
61typedef u16(*otp_read_bit_t) (void *oh, chipcregs_t *cc, uint off);
62typedef int (*otp_read_region_t) (si_t *sih, int region, u16 *data,
7cc4a4c0
JC
63 uint *wlen);
64typedef int (*otp_nvread_t) (void *oh, char *data, uint *len);
a9533e7e
HP
65
66/* OTP function struct */
67typedef 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
76typedef struct {
77 uint ccrev; /* chipc revision */
78 otp_fn_t *fn; /* OTP functions */
79 si_t *sih; /* Saved sb handle */
a9533e7e
HP
80
81#ifdef BCMIPXOTP
82 /* IPX OTP section */
7d4df48e
GKH
83 u16 wsize; /* Size of otp in words */
84 u16 rows; /* Geometry */
85 u16 cols; /* Geometry */
66cbd3ab 86 u32 status; /* Flag bits (lock/prog/rv).
a9533e7e
HP
87 * (Reflected only when OTP is power cycled)
88 */
7d4df48e
GKH
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 */
a9533e7e
HP
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
107static 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 */
e18d5313 153#define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */
a9533e7e
HP
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
161static 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 */
168static int ipxotp_size(void *oh)
169{
170 otpinfo_t *oi = (otpinfo_t *) oh;
171 return (int)oi->wsize * 2;
172}
173
7d4df48e 174static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
a9533e7e
HP
175{
176 otpinfo_t *oi;
177
178 oi = (otpinfo_t *) oh;
179
180 ASSERT(wn < oi->wsize);
181 ASSERT(cc != NULL);
182
ff31c54c 183 return R_REG(&cc->sromotp[wn]);
a9533e7e
HP
184}
185
7d4df48e 186static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
a9533e7e
HP
187{
188 otpinfo_t *oi = (otpinfo_t *) oh;
189 uint k, row, col;
66cbd3ab 190 u32 otpp, st;
a9533e7e
HP
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);
ff31c54c 199 W_REG(&cc->otpprog, otpp);
a9533e7e
HP
200
201 for (k = 0;
ff31c54c 202 ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
62145822
JC
203 && (k < OTPP_TRIES); k++)
204 ;
a9533e7e
HP
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
25985edc 216/* Calculate max HW/SW region byte size by subtracting fuse region and checksum size,
a9533e7e
HP
217 * osizew is oi->wsize (OTP size - GU size) in words
218 */
7cc4a4c0 219static int ipxotp_max_rgnsz(si_t *sih, int osizew)
a9533e7e
HP
220{
221 int ret = 0;
222
dfa26436 223 switch (sih->chip) {
a9533e7e
HP
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:
25985edc 232 ASSERT(0); /* Don't know about this chip */
a9533e7e
HP
233 }
234
235 return ret;
236}
237
a9d0fffa 238static void _ipxotp_init(otpinfo_t *oi, chipcregs_t *cc)
a2627bc0 239{
a9533e7e 240 uint k;
66cbd3ab 241 u32 otpp, st;
a9533e7e
HP
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
ff31c54c 261 W_REG(&cc->otpprog, otpp);
a9533e7e 262 for (k = 0;
ff31c54c 263 ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
62145822
JC
264 && (k < OTPP_TRIES); k++)
265 ;
a9533e7e
HP
266 if (k >= OTPP_TRIES) {
267 return;
268 }
269
270 /* Read OTP lock bits and subregion programmed indication bits */
ff31c54c 271 oi->status = R_REG(&cc->otpstatus);
a9533e7e 272
dfa26436
AS
273 if ((oi->sih->chip == BCM43224_CHIP_ID)
274 || (oi->sih->chip == BCM43225_CHIP_ID)) {
66cbd3ab 275 u32 p_bits;
a9533e7e
HP
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
a9d0fffa 309static void *ipxotp_init(si_t *sih)
a2627bc0 310{
a9533e7e
HP
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
7d4df48e 374static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
a9533e7e
HP
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
7cc4a4c0 460static int ipxotp_nvread(void *oh, char *data, uint *len)
a9533e7e
HP
461{
462 return BCME_UNSUPPORTED;
463}
464
465static 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
556static int hndotp_status(void *oh)
557{
558 otpinfo_t *oi = (otpinfo_t *) oh;
90ea2296 559 return (int)(oi->hwprot | oi->signvalid);
a9533e7e
HP
560}
561
562static int hndotp_size(void *oh)
563{
564 otpinfo_t *oi = (otpinfo_t *) oh;
90ea2296 565 return (int)(oi->size);
a9533e7e
HP
566}
567
7d4df48e 568static u16 hndotp_otpr(void *oh, chipcregs_t *cc, uint wn)
a9533e7e 569{
26bcc181 570#ifdef BCMDBG
a9533e7e 571 otpinfo_t *oi = (otpinfo_t *) oh;
26bcc181 572#endif
7d4df48e 573 volatile u16 *ptr;
a9533e7e
HP
574
575 ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF));
576 ASSERT(cc != NULL);
577
7d4df48e 578 ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
ff31c54c 579 return R_REG(&ptr[wn]);
a9533e7e
HP
580}
581
7d4df48e 582static u16 hndotp_otproff(void *oh, chipcregs_t *cc, int woff)
a9533e7e
HP
583{
584 otpinfo_t *oi = (otpinfo_t *) oh;
7d4df48e 585 volatile u16 *ptr;
a9533e7e
HP
586
587 ASSERT(woff >= (-((int)oi->size / 2)));
588 ASSERT(woff < OTP_LIM_OFF);
589 ASSERT(cc != NULL);
590
7d4df48e 591 ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
a9533e7e 592
ff31c54c 593 return R_REG(&ptr[(oi->size / 2) + woff]);
a9533e7e
HP
594}
595
7d4df48e 596static u16 hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx)
a9533e7e 597{
a9533e7e 598 uint k, row, col;
66cbd3ab 599 u32 otpp, st;
a9533e7e 600
a9533e7e
HP
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
ff31c54c
AS
607 W_REG(&cc->otpprog, otpp);
608 st = R_REG(&cc->otpprog);
a9533e7e
HP
609 for (k = 0;
610 ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES);
611 k++)
ff31c54c 612 st = R_REG(&cc->otpprog);
a9533e7e
HP
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;
7d4df48e 621 return (u16) st;
a9533e7e
HP
622}
623
a9d0fffa 624static void *hndotp_init(si_t *sih)
a2627bc0 625{
a9533e7e
HP
626 uint idx;
627 chipcregs_t *cc;
628 otpinfo_t *oi;
66cbd3ab 629 u32 cap = 0, clkdiv, otpdiv = 0;
a9533e7e 630 void *ret = NULL;
a9533e7e
HP
631
632 oi = &otpinfo;
633
634 idx = si_coreidx(sih);
a9533e7e
HP
635
636 /* Check for otp */
ca8c1e59
JC
637 cc = si_setcoreidx(sih, SI_CC_IDX);
638 if (cc != NULL) {
ff31c54c 639 cap = R_REG(&cc->capabilities);
a9533e7e
HP
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
ff31c54c 662 oi->hwprot = (int)(R_REG(&cc->otpstatus) & OTPS_PROTECT);
a9533e7e
HP
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) {
ff31c54c 682 clkdiv = R_REG(&cc->clkdiv);
a9533e7e
HP
683 clkdiv =
684 (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT);
ff31c54c 685 W_REG(&cc->clkdiv, clkdiv);
a9533e7e 686 }
7383141b 687 udelay(10);
a9533e7e
HP
688
689 ret = (void *)oi;
690 }
691
692 out: /* All done */
693 si_setcoreidx(sih, idx);
694
695 return ret;
696}
697
7d4df48e 698static int hndotp_read_region(void *oh, int region, u16 *data, uint *wlen)
a9533e7e
HP
699{
700 otpinfo_t *oi = (otpinfo_t *) oh;
66cbd3ab 701 u32 idx, st;
a9533e7e
HP
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
7cc4a4c0 728static int hndotp_nvread(void *oh, char *data, uint *len)
a9533e7e
HP
729{
730 int rc = 0;
731 otpinfo_t *oi = (otpinfo_t *) oh;
66cbd3ab 732 u32 base, bound, lim = 0, st;
a9533e7e 733 int i, chunk, gchunks, tsz = 0;
66cbd3ab 734 u32 idx;
a9533e7e
HP
735 chipcregs_t *cc;
736 uint offset;
7d4df48e 737 u16 *rawotp = NULL;
a9533e7e
HP
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);
5fcc1fcb 752 rawotp = kmalloc(lim, GFP_ATOMIC);
ca8c1e59 753 if (rawotp == NULL) {
a9533e7e
HP
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 }
36ef9a1e 800 if (hndcrc16((u8 *) &rawotp[i], rsz,
a9533e7e
HP
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 }
02160695 809 memcpy(&data[offset], &rawotp[i + 2], dsz);
a9533e7e
HP
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:
46d994b1 833 kfree(rawotp);
a9533e7e
HP
834 si_setcoreidx(oi->sih, idx);
835
836 return rc;
837}
838
839static 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
862int otp_status(void *oh)
863{
864 otpinfo_t *oi = (otpinfo_t *) oh;
865
866 return oi->fn->status(oh);
867}
868
869int otp_size(void *oh)
870{
871 otpinfo_t *oi = (otpinfo_t *) oh;
872
873 return oi->fn->size(oh);
874}
875
7d4df48e 876u16 otp_read_bit(void *oh, uint offset)
a9533e7e
HP
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);
7d4df48e 881 u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
a9533e7e
HP
882 si_setcoreidx(oi->sih, idx);
883 return readBit;
884}
885
a9d0fffa 886void *otp_init(si_t *sih)
a2627bc0 887{
a9533e7e
HP
888 otpinfo_t *oi;
889 void *ret = NULL;
890
891 oi = &otpinfo;
9249ede9 892 memset(oi, 0, sizeof(otpinfo_t));
a9533e7e
HP
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;
a9533e7e
HP
911
912 ret = (oi->fn->init) (sih);
913
914 return ret;
915}
916
917int
a9d0fffa 918otp_read_region(si_t *sih, int region, u16 *data,
7cc4a4c0 919 uint *wlen) {
0965ae88 920 bool wasup = false;
a9533e7e
HP
921 void *oh;
922 int err = 0;
923
ca8c1e59
JC
924 wasup = si_is_otp_powered(sih);
925 if (!wasup)
0f0881b0 926 si_otp_power(sih, true);
a9533e7e
HP
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)
0965ae88 943 si_otp_power(sih, false);
a9533e7e
HP
944
945 return err;
946}
947
7cc4a4c0 948int otp_nvread(void *oh, char *data, uint *len)
a9533e7e
HP
949{
950 otpinfo_t *oi = (otpinfo_t *) oh;
951
952 return oi->fn->nvread(oh, data, len);
953}