]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/brcm80211/brcmsmac/bcmotp.c
staging: brcm80211: renamed utility module related files
[mv-sheeva.git] / drivers / staging / brcm80211 / brcmsmac / bcmotp.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <linux/delay.h>
18 #include <linux/kernel.h>
19 #include <linux/string.h>
20 #include <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 <brcmu_utils.h>
27 #include <aiutils.h>
28 #include <bcmsoc.h>
29 #include <chipcommon.h>
30 #include <bcmotp.h>
31
32 #define OTPS_GUP_MASK           0x00000f00
33 #define OTPS_GUP_SHIFT          8
34 #define OTPS_GUP_HW             0x00000100      /* h/w subregion is programmed */
35 #define OTPS_GUP_SW             0x00000200      /* s/w subregion is programmed */
36 #define OTPS_GUP_CI             0x00000400      /* chipid/pkgopt subregion is programmed */
37 #define OTPS_GUP_FUSE           0x00000800      /* fuse subregion is programmed */
38
39 /* Fields in otpprog in rev >= 21 */
40 #define OTPP_COL_MASK           0x000000ff
41 #define OTPP_COL_SHIFT          0
42 #define OTPP_ROW_MASK           0x0000ff00
43 #define OTPP_ROW_SHIFT          8
44 #define OTPP_OC_MASK            0x0f000000
45 #define OTPP_OC_SHIFT           24
46 #define OTPP_READERR            0x10000000
47 #define OTPP_VALUE_MASK         0x20000000
48 #define OTPP_VALUE_SHIFT        29
49 #define OTPP_START_BUSY         0x80000000
50 #define OTPP_READ               0x40000000
51
52 /* Opcodes for OTPP_OC field */
53 #define OTPPOC_READ             0
54 #define OTPPOC_BIT_PROG         1
55 #define OTPPOC_VERIFY           3
56 #define OTPPOC_INIT             4
57 #define OTPPOC_SET              5
58 #define OTPPOC_RESET            6
59 #define OTPPOC_OCST             7
60 #define OTPPOC_ROW_LOCK         8
61 #define OTPPOC_PRESCN_TEST      9
62
63 #define OTPTYPE_IPX(ccrev)      ((ccrev) == 21 || (ccrev) >= 23)
64
65 #define OTPP_TRIES      10000000        /* # of tries for OTPP */
66
67 #define MAXNUMRDES              9       /* Maximum OTP redundancy entries */
68
69 /* OTP common function type */
70 typedef int (*otp_status_t) (void *oh);
71 typedef int (*otp_size_t) (void *oh);
72 typedef void *(*otp_init_t) (struct si_pub *sih);
73 typedef u16(*otp_read_bit_t) (void *oh, chipcregs_t *cc, uint off);
74 typedef int (*otp_read_region_t) (struct si_pub *sih, int region, u16 *data,
75                                   uint *wlen);
76 typedef int (*otp_nvread_t) (void *oh, char *data, uint *len);
77
78 /* OTP function struct */
79 typedef struct otp_fn_s {
80         otp_size_t size;
81         otp_read_bit_t read_bit;
82         otp_init_t init;
83         otp_read_region_t read_region;
84         otp_nvread_t nvread;
85         otp_status_t status;
86 } otp_fn_t;
87
88 typedef struct {
89         uint ccrev;             /* chipc revision */
90         otp_fn_t *fn;           /* OTP functions */
91         struct si_pub *sih;             /* Saved sb handle */
92
93         /* IPX OTP section */
94         u16 wsize;              /* Size of otp in words */
95         u16 rows;               /* Geometry */
96         u16 cols;               /* Geometry */
97         u32 status;             /* Flag bits (lock/prog/rv).
98                                  * (Reflected only when OTP is power cycled)
99                                  */
100         u16 hwbase;             /* hardware subregion offset */
101         u16 hwlim;              /* hardware subregion boundary */
102         u16 swbase;             /* software subregion offset */
103         u16 swlim;              /* software subregion boundary */
104         u16 fbase;              /* fuse subregion offset */
105         u16 flim;               /* fuse subregion boundary */
106         int otpgu_base;         /* offset to General Use Region */
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 #define HWSW_RGN(rgn)           (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
125
126 /* OTP layout */
127 /* CC revs 21, 24 and 27 OTP General Use Region word offset */
128 #define REVA4_OTPGU_BASE        12
129
130 /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
131 #define REVB8_OTPGU_BASE        20
132
133 /* CC rev 36 OTP General Use Region word offset */
134 #define REV36_OTPGU_BASE        12
135
136 /* Subregion word offsets in General Use region */
137 #define OTPGU_HSB_OFF           0
138 #define OTPGU_SFB_OFF           1
139 #define OTPGU_CI_OFF            2
140 #define OTPGU_P_OFF             3
141 #define OTPGU_SROM_OFF          4
142
143 /* Flag bit offsets in General Use region  */
144 #define OTPGU_HWP_OFF           60
145 #define OTPGU_SWP_OFF           61
146 #define OTPGU_CIP_OFF           62
147 #define OTPGU_FUSEP_OFF         63
148 #define OTPGU_CIP_MSK           0x4000
149 #define OTPGU_P_MSK             0xf000
150 #define OTPGU_P_SHIFT           (OTPGU_HWP_OFF % 16)
151
152 /* OTP Size */
153 #define OTP_SZ_FU_324           ((roundup(324, 8))/8)   /* 324 bits */
154 #define OTP_SZ_FU_288           (288/8) /* 288 bits */
155 #define OTP_SZ_FU_216           (216/8) /* 216 bits */
156 #define OTP_SZ_FU_72            (72/8)  /* 72 bits */
157 #define OTP_SZ_CHECKSUM         (16/8)  /* 16 bits */
158 #define OTP4315_SWREG_SZ        178     /* 178 bytes */
159 #define OTP_SZ_FU_144           (144/8) /* 144 bits */
160
161 static int ipxotp_status(void *oh)
162 {
163         otpinfo_t *oi = (otpinfo_t *) oh;
164         return (int)(oi->status);
165 }
166
167 /* Return size in bytes */
168 static int ipxotp_size(void *oh)
169 {
170         otpinfo_t *oi = (otpinfo_t *) oh;
171         return (int)oi->wsize * 2;
172 }
173
174 static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
175 {
176         otpinfo_t *oi;
177
178         oi = (otpinfo_t *) oh;
179
180         return R_REG(&cc->sromotp[wn]);
181 }
182
183 static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
184 {
185         otpinfo_t *oi = (otpinfo_t *) oh;
186         uint k, row, col;
187         u32 otpp, st;
188
189         row = off / oi->cols;
190         col = off % oi->cols;
191
192         otpp = OTPP_START_BUSY |
193             ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
194             ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
195             ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
196         W_REG(&cc->otpprog, otpp);
197
198         for (k = 0;
199              ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
200              && (k < OTPP_TRIES); k++)
201                 ;
202         if (k >= OTPP_TRIES) {
203                 return 0xffff;
204         }
205         if (st & OTPP_READERR) {
206                 return 0xffff;
207         }
208         st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
209
210         return (int)st;
211 }
212
213 /* Calculate max HW/SW region byte size by subtracting fuse region and checksum size,
214  * osizew is oi->wsize (OTP size - GU size) in words
215  */
216 static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
217 {
218         int ret = 0;
219
220         switch (sih->chip) {
221         case BCM43224_CHIP_ID:
222         case BCM43225_CHIP_ID:
223                 ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
224                 break;
225         case BCM4313_CHIP_ID:
226                 ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
227                 break;
228         default:
229                 break;  /* Don't know about this chip */
230         }
231
232         return ret;
233 }
234
235 static void _ipxotp_init(otpinfo_t *oi, chipcregs_t *cc)
236 {
237         uint k;
238         u32 otpp, st;
239
240         /* record word offset of General Use Region for various chipcommon revs */
241         if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
242             || oi->sih->ccrev == 27) {
243                 oi->otpgu_base = REVA4_OTPGU_BASE;
244         } else if (oi->sih->ccrev == 36) {
245                 /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
246                 if (oi->wsize >= 128)
247                         oi->otpgu_base = REVB8_OTPGU_BASE;
248                 else
249                         oi->otpgu_base = REV36_OTPGU_BASE;
250         } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
251                 oi->otpgu_base = REVB8_OTPGU_BASE;
252         }
253
254         /* First issue an init command so the status is up to date */
255         otpp =
256             OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
257
258         W_REG(&cc->otpprog, otpp);
259         for (k = 0;
260              ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
261              && (k < OTPP_TRIES); k++)
262                 ;
263         if (k >= OTPP_TRIES) {
264                 return;
265         }
266
267         /* Read OTP lock bits and subregion programmed indication bits */
268         oi->status = R_REG(&cc->otpstatus);
269
270         if ((oi->sih->chip == BCM43224_CHIP_ID)
271             || (oi->sih->chip == BCM43225_CHIP_ID)) {
272                 u32 p_bits;
273                 p_bits =
274                     (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
275                      OTPGU_P_MSK)
276                     >> OTPGU_P_SHIFT;
277                 oi->status |= (p_bits << OTPS_GUP_SHIFT);
278         }
279
280         /*
281          * h/w region base and fuse region limit are fixed to the top and
282          * the bottom of the general use region. Everything else can be flexible.
283          */
284         oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
285         oi->hwlim = oi->wsize;
286         if (oi->status & OTPS_GUP_HW) {
287                 oi->hwlim =
288                     ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
289                 oi->swbase = oi->hwlim;
290         } else
291                 oi->swbase = oi->hwbase;
292
293         /* subtract fuse and checksum from beginning */
294         oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
295
296         if (oi->status & OTPS_GUP_SW) {
297                 oi->swlim =
298                     ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
299                 oi->fbase = oi->swlim;
300         } else
301                 oi->fbase = oi->swbase;
302
303         oi->flim = oi->wsize;
304 }
305
306 static void *ipxotp_init(struct si_pub *sih)
307 {
308         uint idx;
309         chipcregs_t *cc;
310         otpinfo_t *oi;
311
312         /* Make sure we're running IPX OTP */
313         if (!OTPTYPE_IPX(sih->ccrev))
314                 return NULL;
315
316         /* Make sure OTP is not disabled */
317         if (ai_is_otp_disabled(sih))
318                 return NULL;
319
320         /* Make sure OTP is powered up */
321         if (!ai_is_otp_powered(sih))
322                 return NULL;
323
324         oi = &otpinfo;
325
326         /* Check for otp size */
327         switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
328         case 0:
329                 /* Nothing there */
330                 return NULL;
331         case 1:         /* 32x64 */
332                 oi->rows = 32;
333                 oi->cols = 64;
334                 oi->wsize = 128;
335                 break;
336         case 2:         /* 64x64 */
337                 oi->rows = 64;
338                 oi->cols = 64;
339                 oi->wsize = 256;
340                 break;
341         case 5:         /* 96x64 */
342                 oi->rows = 96;
343                 oi->cols = 64;
344                 oi->wsize = 384;
345                 break;
346         case 7:         /* 16x64 *//* 1024 bits */
347                 oi->rows = 16;
348                 oi->cols = 64;
349                 oi->wsize = 64;
350                 break;
351         default:
352                 /* Don't know the geometry */
353                 return NULL;
354         }
355
356         /* Retrieve OTP region info */
357         idx = ai_coreidx(sih);
358         cc = ai_setcoreidx(sih, SI_CC_IDX);
359
360         _ipxotp_init(oi, cc);
361
362         ai_setcoreidx(sih, idx);
363
364         return (void *)oi;
365 }
366
367 static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
368 {
369         otpinfo_t *oi = (otpinfo_t *) oh;
370         uint idx;
371         chipcregs_t *cc;
372         uint base, i, sz;
373
374         /* Validate region selection */
375         switch (region) {
376         case OTP_HW_RGN:
377                 sz = (uint) oi->hwlim - oi->hwbase;
378                 if (!(oi->status & OTPS_GUP_HW)) {
379                         *wlen = sz;
380                         return -ENODATA;
381                 }
382                 if (*wlen < sz) {
383                         *wlen = sz;
384                         return -EOVERFLOW;
385                 }
386                 base = oi->hwbase;
387                 break;
388         case OTP_SW_RGN:
389                 sz = ((uint) oi->swlim - oi->swbase);
390                 if (!(oi->status & OTPS_GUP_SW)) {
391                         *wlen = sz;
392                         return -ENODATA;
393                 }
394                 if (*wlen < sz) {
395                         *wlen = sz;
396                         return -EOVERFLOW;
397                 }
398                 base = oi->swbase;
399                 break;
400         case OTP_CI_RGN:
401                 sz = OTPGU_CI_SZ;
402                 if (!(oi->status & OTPS_GUP_CI)) {
403                         *wlen = sz;
404                         return -ENODATA;
405                 }
406                 if (*wlen < sz) {
407                         *wlen = sz;
408                         return -EOVERFLOW;
409                 }
410                 base = oi->otpgu_base + OTPGU_CI_OFF;
411                 break;
412         case OTP_FUSE_RGN:
413                 sz = (uint) oi->flim - oi->fbase;
414                 if (!(oi->status & OTPS_GUP_FUSE)) {
415                         *wlen = sz;
416                         return -ENODATA;
417                 }
418                 if (*wlen < sz) {
419                         *wlen = sz;
420                         return -EOVERFLOW;
421                 }
422                 base = oi->fbase;
423                 break;
424         case OTP_ALL_RGN:
425                 sz = ((uint) oi->flim - oi->hwbase);
426                 if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
427                         *wlen = sz;
428                         return -ENODATA;
429                 }
430                 if (*wlen < sz) {
431                         *wlen = sz;
432                         return -EOVERFLOW;
433                 }
434                 base = oi->hwbase;
435                 break;
436         default:
437                 return -EINVAL;
438         }
439
440         idx = ai_coreidx(oi->sih);
441         cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
442
443         /* Read the data */
444         for (i = 0; i < sz; i++)
445                 data[i] = ipxotp_otpr(oh, cc, base + i);
446
447         ai_setcoreidx(oi->sih, idx);
448         *wlen = sz;
449         return 0;
450 }
451
452 static int ipxotp_nvread(void *oh, char *data, uint *len)
453 {
454         return -ENOTSUPP;
455 }
456
457 static otp_fn_t ipxotp_fn = {
458         (otp_size_t) ipxotp_size,
459         (otp_read_bit_t) ipxotp_read_bit,
460
461         (otp_init_t) ipxotp_init,
462         (otp_read_region_t) ipxotp_read_region,
463         (otp_nvread_t) ipxotp_nvread,
464
465         (otp_status_t) ipxotp_status
466 };
467
468 /*
469  *      otp_status()
470  *      otp_size()
471  *      otp_read_bit()
472  *      otp_init()
473  *      otp_read_region()
474  *      otp_nvread()
475  */
476
477 int otp_status(void *oh)
478 {
479         otpinfo_t *oi = (otpinfo_t *) oh;
480
481         return oi->fn->status(oh);
482 }
483
484 int otp_size(void *oh)
485 {
486         otpinfo_t *oi = (otpinfo_t *) oh;
487
488         return oi->fn->size(oh);
489 }
490
491 u16 otp_read_bit(void *oh, uint offset)
492 {
493         otpinfo_t *oi = (otpinfo_t *) oh;
494         uint idx = ai_coreidx(oi->sih);
495         chipcregs_t *cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
496         u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
497         ai_setcoreidx(oi->sih, idx);
498         return readBit;
499 }
500
501 void *otp_init(struct si_pub *sih)
502 {
503         otpinfo_t *oi;
504         void *ret = NULL;
505
506         oi = &otpinfo;
507         memset(oi, 0, sizeof(otpinfo_t));
508
509         oi->ccrev = sih->ccrev;
510
511         if (OTPTYPE_IPX(oi->ccrev))
512                 oi->fn = &ipxotp_fn;
513
514         if (oi->fn == NULL) {
515                 return NULL;
516         }
517
518         oi->sih = sih;
519
520         ret = (oi->fn->init) (sih);
521
522         return ret;
523 }
524
525 int
526 otp_read_region(struct si_pub *sih, int region, u16 *data,
527                                  uint *wlen) {
528         bool wasup = false;
529         void *oh;
530         int err = 0;
531
532         wasup = ai_is_otp_powered(sih);
533         if (!wasup)
534                 ai_otp_power(sih, true);
535
536         if (!ai_is_otp_powered(sih) || ai_is_otp_disabled(sih)) {
537                 err = -EPERM;
538                 goto out;
539         }
540
541         oh = otp_init(sih);
542         if (oh == NULL) {
543                 err = -EBADE;
544                 goto out;
545         }
546
547         err = (((otpinfo_t *) oh)->fn->read_region) (oh, region, data, wlen);
548
549  out:
550         if (!wasup)
551                 ai_otp_power(sih, false);
552
553         return err;
554 }
555
556 int otp_nvread(void *oh, char *data, uint *len)
557 {
558         otpinfo_t *oi = (otpinfo_t *) oh;
559
560         return oi->fn->nvread(oh, data, len);
561 }