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