]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/net/wireless/brcm80211/brcmsmac/otp.c
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.
18 #include <linux/errno.h>
19 #include <linux/string.h>
21 #include <brcm_hw_ids.h>
22 #include <chipcommon.h>
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
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
50 /* Opcodes for OTPP_OC field */
52 #define OTPPOC_BIT_PROG 1
53 #define OTPPOC_VERIFY 3
56 #define OTPPOC_RESET 6
58 #define OTPPOC_ROW_LOCK 8
59 #define OTPPOC_PRESCN_TEST 9
61 #define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23)
63 #define OTPP_TRIES 10000000 /* # of tries for OTPP */
65 #define MAXNUMRDES 9 /* Maximum OTP redundancy entries */
67 /* Fixed size subregions sizes in words */
72 /* OTP function struct */
74 int (*init
)(struct si_pub
*sih
, struct otpinfo
*oi
);
75 int (*read_region
)(struct otpinfo
*oi
, int region
, u16
*data
,
80 uint ccrev
; /* chipc revision */
81 const struct otp_fn_s
*fn
; /* OTP functions */
82 struct si_pub
*sih
; /* Saved sb handle */
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)
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 */
101 /* CC revs 21, 24 and 27 OTP General Use Region word offset */
102 #define REVA4_OTPGU_BASE 12
104 /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
105 #define REVB8_OTPGU_BASE 20
107 /* CC rev 36 OTP General Use Region word offset */
108 #define REV36_OTPGU_BASE 12
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
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)
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 */
136 ipxotp_otpr(struct otpinfo
*oi
, struct chipcregs __iomem
*cc
, uint wn
)
138 return R_REG(&cc
->sromotp
[wn
]);
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
145 static int ipxotp_max_rgnsz(struct si_pub
*sih
, int osizew
)
149 switch (ai_get_chip_id(sih
)) {
150 case BCM43224_CHIP_ID
:
151 case BCM43225_CHIP_ID
:
152 ret
= osizew
* 2 - OTP_SZ_FU_72
- OTP_SZ_CHECKSUM
;
154 case BCM4313_CHIP_ID
:
155 ret
= osizew
* 2 - OTP_SZ_FU_72
- OTP_SZ_CHECKSUM
;
158 break; /* Don't know about this chip */
164 static void _ipxotp_init(struct otpinfo
*oi
, struct chipcregs __iomem
*cc
)
170 * record word offset of General Use Region
171 * for various chipcommon revs
173 if (oi
->ccrev
== 21 || oi
->ccrev
== 24
174 || oi
->ccrev
== 27) {
175 oi
->otpgu_base
= REVA4_OTPGU_BASE
;
176 } else if (oi
->ccrev
== 36) {
178 * OTP size greater than equal to 2KB (128 words),
179 * otpgu_base is similar to rev23
181 if (oi
->wsize
>= 128)
182 oi
->otpgu_base
= REVB8_OTPGU_BASE
;
184 oi
->otpgu_base
= REV36_OTPGU_BASE
;
185 } else if (oi
->ccrev
== 23 || oi
->ccrev
>= 25) {
186 oi
->otpgu_base
= REVB8_OTPGU_BASE
;
189 /* First issue an init command so the status is up to date */
191 OTPP_START_BUSY
| ((OTPPOC_INIT
<< OTPP_OC_SHIFT
) & OTPP_OC_MASK
);
193 W_REG(&cc
->otpprog
, otpp
);
195 ((st
= R_REG(&cc
->otpprog
)) & OTPP_START_BUSY
)
196 && (k
< OTPP_TRIES
); k
++)
201 /* Read OTP lock bits and subregion programmed indication bits */
202 oi
->status
= R_REG(&cc
->otpstatus
);
204 if ((ai_get_chip_id(oi
->sih
) == BCM43224_CHIP_ID
)
205 || (ai_get_chip_id(oi
->sih
) == BCM43225_CHIP_ID
)) {
208 (ipxotp_otpr(oi
, cc
, oi
->otpgu_base
+ OTPGU_P_OFF
) &
211 oi
->status
|= (p_bits
<< OTPS_GUP_SHIFT
);
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.
219 oi
->hwbase
= oi
->otpgu_base
+ OTPGU_SROM_OFF
;
220 oi
->hwlim
= oi
->wsize
;
221 if (oi
->status
& OTPS_GUP_HW
) {
223 ipxotp_otpr(oi
, cc
, oi
->otpgu_base
+ OTPGU_HSB_OFF
) / 16;
224 oi
->swbase
= oi
->hwlim
;
226 oi
->swbase
= oi
->hwbase
;
228 /* subtract fuse and checksum from beginning */
229 oi
->swlim
= ipxotp_max_rgnsz(oi
->sih
, oi
->wsize
) / 2;
231 if (oi
->status
& OTPS_GUP_SW
) {
233 ipxotp_otpr(oi
, cc
, oi
->otpgu_base
+ OTPGU_SFB_OFF
) / 16;
234 oi
->fbase
= oi
->swlim
;
236 oi
->fbase
= oi
->swbase
;
238 oi
->flim
= oi
->wsize
;
241 static int ipxotp_init(struct si_pub
*sih
, struct otpinfo
*oi
)
244 struct chipcregs __iomem
*cc
;
246 /* Make sure we're running IPX OTP */
247 if (!OTPTYPE_IPX(oi
->ccrev
))
250 /* Make sure OTP is not disabled */
251 if (ai_is_otp_disabled(sih
))
254 /* Check for otp size */
255 switch ((ai_get_cccaps(sih
) & CC_CAP_OTPSIZE
) >> CC_CAP_OTPSIZE_SHIFT
) {
274 case 7: /* 16x64 *//* 1024 bits */
280 /* Don't know the geometry */
284 /* Retrieve OTP region info */
285 idx
= ai_coreidx(sih
);
286 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
288 _ipxotp_init(oi
, cc
);
290 ai_setcoreidx(sih
, idx
);
296 ipxotp_read_region(struct otpinfo
*oi
, int region
, u16
*data
, uint
*wlen
)
299 struct chipcregs __iomem
*cc
;
302 /* Validate region selection */
305 sz
= (uint
) oi
->hwlim
- oi
->hwbase
;
306 if (!(oi
->status
& OTPS_GUP_HW
)) {
317 sz
= ((uint
) oi
->swlim
- oi
->swbase
);
318 if (!(oi
->status
& OTPS_GUP_SW
)) {
330 if (!(oi
->status
& OTPS_GUP_CI
)) {
338 base
= oi
->otpgu_base
+ OTPGU_CI_OFF
;
341 sz
= (uint
) oi
->flim
- oi
->fbase
;
342 if (!(oi
->status
& OTPS_GUP_FUSE
)) {
353 sz
= ((uint
) oi
->flim
- oi
->hwbase
);
354 if (!(oi
->status
& (OTPS_GUP_HW
| OTPS_GUP_SW
))) {
368 idx
= ai_coreidx(oi
->sih
);
369 cc
= ai_setcoreidx(oi
->sih
, SI_CC_IDX
);
372 for (i
= 0; i
< sz
; i
++)
373 data
[i
] = ipxotp_otpr(oi
, cc
, base
+ i
);
375 ai_setcoreidx(oi
->sih
, idx
);
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
,
385 static int otp_init(struct si_pub
*sih
, struct otpinfo
*oi
)
390 memset(oi
, 0, sizeof(struct otpinfo
));
392 oi
->ccrev
= ai_get_ccrev(sih
);
394 if (OTPTYPE_IPX(oi
->ccrev
))
402 ret
= (oi
->fn
->init
) (sih
, oi
);
408 otp_read_region(struct si_pub
*sih
, int region
, u16
*data
, uint
*wlen
) {
409 struct otpinfo otpinfo
;
410 struct otpinfo
*oi
= &otpinfo
;
413 if (ai_is_otp_disabled(sih
)) {
418 err
= otp_init(sih
, oi
);
422 err
= ((oi
)->fn
->read_region
)(oi
, region
, data
, wlen
);