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