~ubuntu-branches/ubuntu/quantal/linux-linaro-mx51/quantal

« back to all changes in this revision

Viewing changes to drivers/staging/brcm80211/brcmsmac/bcmotp.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-3o58a3c1bj7x00rs
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

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