]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/brcm80211/brcmsmac/otp.c
Merge branch 'next/devel' of ssh://master.kernel.org/pub/scm/linux/kernel/git/arm...
[mirror_ubuntu-bionic-kernel.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 <chipcommon.h>
22 #include "aiutils.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 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 };
80
81 struct otpinfo {
82 uint ccrev; /* chipc revision */
83 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 #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 struct otpinfo *oi = (struct otpinfo *) oh;
157 return (int)(oi->status);
158 }
159
160 /* Return size in bytes */
161 static int ipxotp_size(void *oh)
162 {
163 struct otpinfo *oi = (struct otpinfo *) oh;
164 return (int)oi->wsize * 2;
165 }
166
167 static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
168 {
169 struct otpinfo *oi;
170
171 oi = (struct otpinfo *) 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 struct otpinfo *oi = (struct otpinfo *) 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(struct otpinfo *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 struct otpinfo *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 /* OTP is always powered */
314 oi = &otpinfo;
315
316 /* Check for otp size */
317 switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
318 case 0:
319 /* Nothing there */
320 return NULL;
321 case 1: /* 32x64 */
322 oi->rows = 32;
323 oi->cols = 64;
324 oi->wsize = 128;
325 break;
326 case 2: /* 64x64 */
327 oi->rows = 64;
328 oi->cols = 64;
329 oi->wsize = 256;
330 break;
331 case 5: /* 96x64 */
332 oi->rows = 96;
333 oi->cols = 64;
334 oi->wsize = 384;
335 break;
336 case 7: /* 16x64 *//* 1024 bits */
337 oi->rows = 16;
338 oi->cols = 64;
339 oi->wsize = 64;
340 break;
341 default:
342 /* Don't know the geometry */
343 return NULL;
344 }
345
346 /* Retrieve OTP region info */
347 idx = ai_coreidx(sih);
348 cc = ai_setcoreidx(sih, SI_CC_IDX);
349
350 _ipxotp_init(oi, cc);
351
352 ai_setcoreidx(sih, idx);
353
354 return (void *)oi;
355 }
356
357 static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
358 {
359 struct otpinfo *oi = (struct otpinfo *) oh;
360 uint idx;
361 chipcregs_t *cc;
362 uint base, i, sz;
363
364 /* Validate region selection */
365 switch (region) {
366 case OTP_HW_RGN:
367 sz = (uint) oi->hwlim - oi->hwbase;
368 if (!(oi->status & OTPS_GUP_HW)) {
369 *wlen = sz;
370 return -ENODATA;
371 }
372 if (*wlen < sz) {
373 *wlen = sz;
374 return -EOVERFLOW;
375 }
376 base = oi->hwbase;
377 break;
378 case OTP_SW_RGN:
379 sz = ((uint) oi->swlim - oi->swbase);
380 if (!(oi->status & OTPS_GUP_SW)) {
381 *wlen = sz;
382 return -ENODATA;
383 }
384 if (*wlen < sz) {
385 *wlen = sz;
386 return -EOVERFLOW;
387 }
388 base = oi->swbase;
389 break;
390 case OTP_CI_RGN:
391 sz = OTPGU_CI_SZ;
392 if (!(oi->status & OTPS_GUP_CI)) {
393 *wlen = sz;
394 return -ENODATA;
395 }
396 if (*wlen < sz) {
397 *wlen = sz;
398 return -EOVERFLOW;
399 }
400 base = oi->otpgu_base + OTPGU_CI_OFF;
401 break;
402 case OTP_FUSE_RGN:
403 sz = (uint) oi->flim - oi->fbase;
404 if (!(oi->status & OTPS_GUP_FUSE)) {
405 *wlen = sz;
406 return -ENODATA;
407 }
408 if (*wlen < sz) {
409 *wlen = sz;
410 return -EOVERFLOW;
411 }
412 base = oi->fbase;
413 break;
414 case OTP_ALL_RGN:
415 sz = ((uint) oi->flim - oi->hwbase);
416 if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
417 *wlen = sz;
418 return -ENODATA;
419 }
420 if (*wlen < sz) {
421 *wlen = sz;
422 return -EOVERFLOW;
423 }
424 base = oi->hwbase;
425 break;
426 default:
427 return -EINVAL;
428 }
429
430 idx = ai_coreidx(oi->sih);
431 cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
432
433 /* Read the data */
434 for (i = 0; i < sz; i++)
435 data[i] = ipxotp_otpr(oh, cc, base + i);
436
437 ai_setcoreidx(oi->sih, idx);
438 *wlen = sz;
439 return 0;
440 }
441
442 static int ipxotp_nvread(void *oh, char *data, uint *len)
443 {
444 return -ENOTSUPP;
445 }
446
447 static struct otp_fn_s ipxotp_fn = {
448 (otp_size_t) ipxotp_size,
449 (otp_read_bit_t) ipxotp_read_bit,
450
451 (otp_init_t) ipxotp_init,
452 (otp_read_region_t) ipxotp_read_region,
453 (otp_nvread_t) ipxotp_nvread,
454
455 (otp_status_t) ipxotp_status
456 };
457
458 /*
459 * otp_status()
460 * otp_size()
461 * otp_read_bit()
462 * otp_init()
463 * otp_read_region()
464 * otp_nvread()
465 */
466
467 int otp_status(void *oh)
468 {
469 struct otpinfo *oi = (struct otpinfo *) oh;
470
471 return oi->fn->status(oh);
472 }
473
474 int otp_size(void *oh)
475 {
476 struct otpinfo *oi = (struct otpinfo *) oh;
477
478 return oi->fn->size(oh);
479 }
480
481 u16 otp_read_bit(void *oh, uint offset)
482 {
483 struct otpinfo *oi = (struct otpinfo *) oh;
484 uint idx = ai_coreidx(oi->sih);
485 chipcregs_t *cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
486 u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
487 ai_setcoreidx(oi->sih, idx);
488 return readBit;
489 }
490
491 void *otp_init(struct si_pub *sih)
492 {
493 struct otpinfo *oi;
494 void *ret = NULL;
495
496 oi = &otpinfo;
497 memset(oi, 0, sizeof(struct otpinfo));
498
499 oi->ccrev = sih->ccrev;
500
501 if (OTPTYPE_IPX(oi->ccrev))
502 oi->fn = &ipxotp_fn;
503
504 if (oi->fn == NULL) {
505 return NULL;
506 }
507
508 oi->sih = sih;
509
510 ret = (oi->fn->init) (sih);
511
512 return ret;
513 }
514
515 int
516 otp_read_region(struct si_pub *sih, int region, u16 *data,
517 uint *wlen) {
518 void *oh;
519 int err = 0;
520
521 if (ai_is_otp_disabled(sih)) {
522 err = -EPERM;
523 goto out;
524 }
525
526 oh = otp_init(sih);
527 if (oh == NULL) {
528 err = -EBADE;
529 goto out;
530 }
531
532 err = (((struct otpinfo *) oh)->fn->read_region)
533 (oh, region, data, wlen);
534
535 out:
536 return err;
537 }
538
539 int otp_nvread(void *oh, char *data, uint *len)
540 {
541 struct otpinfo *oi = (struct otpinfo *) oh;
542
543 return oi->fn->nvread(oh, data, len);
544 }