Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / drivers / net / wireless / 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 struct otpinfo;
71
72 /* OTP function struct */
73 struct otp_fn_s {
74         int (*init)(struct si_pub *sih, struct otpinfo *oi);
75         int (*read_region)(struct otpinfo *oi, int region, u16 *data,
76                            uint *wlen);
77 };
78
79 struct otpinfo {
80         uint ccrev;             /* chipc revision */
81         const struct otp_fn_s *fn;      /* OTP functions */
82         struct si_pub *sih;             /* Saved sb handle */
83
84         /* IPX OTP section */
85         u16 wsize;              /* Size of otp in words */
86         u16 rows;               /* Geometry */
87         u16 cols;               /* Geometry */
88         u32 status;             /* Flag bits (lock/prog/rv).
89                                  * (Reflected only when OTP is power cycled)
90                                  */
91         u16 hwbase;             /* hardware subregion offset */
92         u16 hwlim;              /* hardware subregion boundary */
93         u16 swbase;             /* software subregion offset */
94         u16 swlim;              /* software subregion boundary */
95         u16 fbase;              /* fuse subregion offset */
96         u16 flim;               /* fuse subregion boundary */
97         int otpgu_base;         /* offset to General Use Region */
98 };
99
100 /* OTP layout */
101 /* CC revs 21, 24 and 27 OTP General Use Region word offset */
102 #define REVA4_OTPGU_BASE        12
103
104 /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
105 #define REVB8_OTPGU_BASE        20
106
107 /* CC rev 36 OTP General Use Region word offset */
108 #define REV36_OTPGU_BASE        12
109
110 /* Subregion word offsets in General Use region */
111 #define OTPGU_HSB_OFF           0
112 #define OTPGU_SFB_OFF           1
113 #define OTPGU_CI_OFF            2
114 #define OTPGU_P_OFF             3
115 #define OTPGU_SROM_OFF          4
116
117 /* Flag bit offsets in General Use region  */
118 #define OTPGU_HWP_OFF           60
119 #define OTPGU_SWP_OFF           61
120 #define OTPGU_CIP_OFF           62
121 #define OTPGU_FUSEP_OFF         63
122 #define OTPGU_CIP_MSK           0x4000
123 #define OTPGU_P_MSK             0xf000
124 #define OTPGU_P_SHIFT           (OTPGU_HWP_OFF % 16)
125
126 /* OTP Size */
127 #define OTP_SZ_FU_324           ((roundup(324, 8))/8)   /* 324 bits */
128 #define OTP_SZ_FU_288           (288/8) /* 288 bits */
129 #define OTP_SZ_FU_216           (216/8) /* 216 bits */
130 #define OTP_SZ_FU_72            (72/8)  /* 72 bits */
131 #define OTP_SZ_CHECKSUM         (16/8)  /* 16 bits */
132 #define OTP4315_SWREG_SZ        178     /* 178 bytes */
133 #define OTP_SZ_FU_144           (144/8) /* 144 bits */
134
135 static u16
136 ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn)
137 {
138         return R_REG(&cc->sromotp[wn]);
139 }
140
141 /*
142  * Calculate max HW/SW region byte size by subtracting fuse region
143  * and checksum size, osizew is oi->wsize (OTP size - GU size) in words
144  */
145 static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
146 {
147         int ret = 0;
148
149         switch (sih->chip) {
150         case BCM43224_CHIP_ID:
151         case BCM43225_CHIP_ID:
152                 ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
153                 break;
154         case BCM4313_CHIP_ID:
155                 ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
156                 break;
157         default:
158                 break;  /* Don't know about this chip */
159         }
160
161         return ret;
162 }
163
164 static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
165 {
166         uint k;
167         u32 otpp, st;
168
169         /*
170          * record word offset of General Use Region
171          * for various chipcommon revs
172          */
173         if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
174             || oi->sih->ccrev == 27) {
175                 oi->otpgu_base = REVA4_OTPGU_BASE;
176         } else if (oi->sih->ccrev == 36) {
177                 /*
178                  * OTP size greater than equal to 2KB (128 words),
179                  * otpgu_base is similar to rev23
180                  */
181                 if (oi->wsize >= 128)
182                         oi->otpgu_base = REVB8_OTPGU_BASE;
183                 else
184                         oi->otpgu_base = REV36_OTPGU_BASE;
185         } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
186                 oi->otpgu_base = REVB8_OTPGU_BASE;
187         }
188
189         /* First issue an init command so the status is up to date */
190         otpp =
191             OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
192
193         W_REG(&cc->otpprog, otpp);
194         for (k = 0;
195              ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
196              && (k < OTPP_TRIES); k++)
197                 ;
198         if (k >= OTPP_TRIES)
199                 return;
200
201         /* Read OTP lock bits and subregion programmed indication bits */
202         oi->status = R_REG(&cc->otpstatus);
203
204         if ((oi->sih->chip == BCM43224_CHIP_ID)
205             || (oi->sih->chip == BCM43225_CHIP_ID)) {
206                 u32 p_bits;
207                 p_bits =
208                     (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
209                      OTPGU_P_MSK)
210                     >> OTPGU_P_SHIFT;
211                 oi->status |= (p_bits << OTPS_GUP_SHIFT);
212         }
213
214         /*
215          * h/w region base and fuse region limit are fixed to
216          * the top and the bottom of the general use region.
217          * Everything else can be flexible.
218          */
219         oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
220         oi->hwlim = oi->wsize;
221         if (oi->status & OTPS_GUP_HW) {
222                 oi->hwlim =
223                     ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
224                 oi->swbase = oi->hwlim;
225         } else
226                 oi->swbase = oi->hwbase;
227
228         /* subtract fuse and checksum from beginning */
229         oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
230
231         if (oi->status & OTPS_GUP_SW) {
232                 oi->swlim =
233                     ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
234                 oi->fbase = oi->swlim;
235         } else
236                 oi->fbase = oi->swbase;
237
238         oi->flim = oi->wsize;
239 }
240
241 static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
242 {
243         uint idx;
244         struct chipcregs __iomem *cc;
245
246         /* Make sure we're running IPX OTP */
247         if (!OTPTYPE_IPX(sih->ccrev))
248                 return -EBADE;
249
250         /* Make sure OTP is not disabled */
251         if (ai_is_otp_disabled(sih))
252                 return -EBADE;
253
254         /* Check for otp size */
255         switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
256         case 0:
257                 /* Nothing there */
258                 return -EBADE;
259         case 1:         /* 32x64 */
260                 oi->rows = 32;
261                 oi->cols = 64;
262                 oi->wsize = 128;
263                 break;
264         case 2:         /* 64x64 */
265                 oi->rows = 64;
266                 oi->cols = 64;
267                 oi->wsize = 256;
268                 break;
269         case 5:         /* 96x64 */
270                 oi->rows = 96;
271                 oi->cols = 64;
272                 oi->wsize = 384;
273                 break;
274         case 7:         /* 16x64 *//* 1024 bits */
275                 oi->rows = 16;
276                 oi->cols = 64;
277                 oi->wsize = 64;
278                 break;
279         default:
280                 /* Don't know the geometry */
281                 return -EBADE;
282         }
283
284         /* Retrieve OTP region info */
285         idx = ai_coreidx(sih);
286         cc = ai_setcoreidx(sih, SI_CC_IDX);
287
288         _ipxotp_init(oi, cc);
289
290         ai_setcoreidx(sih, idx);
291
292         return 0;
293 }
294
295 static int
296 ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
297 {
298         uint idx;
299         struct chipcregs __iomem *cc;
300         uint base, i, sz;
301
302         /* Validate region selection */
303         switch (region) {
304         case OTP_HW_RGN:
305                 sz = (uint) oi->hwlim - oi->hwbase;
306                 if (!(oi->status & OTPS_GUP_HW)) {
307                         *wlen = sz;
308                         return -ENODATA;
309                 }
310                 if (*wlen < sz) {
311                         *wlen = sz;
312                         return -EOVERFLOW;
313                 }
314                 base = oi->hwbase;
315                 break;
316         case OTP_SW_RGN:
317                 sz = ((uint) oi->swlim - oi->swbase);
318                 if (!(oi->status & OTPS_GUP_SW)) {
319                         *wlen = sz;
320                         return -ENODATA;
321                 }
322                 if (*wlen < sz) {
323                         *wlen = sz;
324                         return -EOVERFLOW;
325                 }
326                 base = oi->swbase;
327                 break;
328         case OTP_CI_RGN:
329                 sz = OTPGU_CI_SZ;
330                 if (!(oi->status & OTPS_GUP_CI)) {
331                         *wlen = sz;
332                         return -ENODATA;
333                 }
334                 if (*wlen < sz) {
335                         *wlen = sz;
336                         return -EOVERFLOW;
337                 }
338                 base = oi->otpgu_base + OTPGU_CI_OFF;
339                 break;
340         case OTP_FUSE_RGN:
341                 sz = (uint) oi->flim - oi->fbase;
342                 if (!(oi->status & OTPS_GUP_FUSE)) {
343                         *wlen = sz;
344                         return -ENODATA;
345                 }
346                 if (*wlen < sz) {
347                         *wlen = sz;
348                         return -EOVERFLOW;
349                 }
350                 base = oi->fbase;
351                 break;
352         case OTP_ALL_RGN:
353                 sz = ((uint) oi->flim - oi->hwbase);
354                 if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
355                         *wlen = sz;
356                         return -ENODATA;
357                 }
358                 if (*wlen < sz) {
359                         *wlen = sz;
360                         return -EOVERFLOW;
361                 }
362                 base = oi->hwbase;
363                 break;
364         default:
365                 return -EINVAL;
366         }
367
368         idx = ai_coreidx(oi->sih);
369         cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
370
371         /* Read the data */
372         for (i = 0; i < sz; i++)
373                 data[i] = ipxotp_otpr(oi, cc, base + i);
374
375         ai_setcoreidx(oi->sih, idx);
376         *wlen = sz;
377         return 0;
378 }
379
380 static const struct otp_fn_s ipxotp_fn = {
381         (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init,
382         (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region,
383 };
384
385 static int otp_init(struct si_pub *sih, struct otpinfo *oi)
386 {
387
388         int ret;
389
390         memset(oi, 0, sizeof(struct otpinfo));
391
392         oi->ccrev = sih->ccrev;
393
394         if (OTPTYPE_IPX(oi->ccrev))
395                 oi->fn = &ipxotp_fn;
396
397         if (oi->fn == NULL)
398                 return -EBADE;
399
400         oi->sih = sih;
401
402         ret = (oi->fn->init) (sih, oi);
403
404         return ret;
405 }
406
407 int
408 otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) {
409         struct otpinfo otpinfo;
410         struct otpinfo *oi = &otpinfo;
411         int err = 0;
412
413         if (ai_is_otp_disabled(sih)) {
414                 err = -EPERM;
415                 goto out;
416         }
417
418         err = otp_init(sih, oi);
419         if (err)
420                 goto out;
421
422         err = ((oi)->fn->read_region)(oi, region, data, wlen);
423
424  out:
425         return err;
426 }