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