2 * Sonics Silicon Backplane PCI-Hostbus related functions.
4 * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
5 * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
6 * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
7 * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
8 * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10 * Derived from the Broadcom 4400 device driver.
11 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
12 * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
13 * Copyright (C) 2006 Broadcom Corporation.
15 * Licensed under the GNU/GPL. See COPYING for details.
18 #include "ssb_private.h"
20 #include <linux/ssb/ssb.h>
21 #include <linux/ssb/ssb_regs.h>
22 #include <linux/slab.h>
23 #include <linux/pci.h>
24 #include <linux/delay.h>
27 /* Define the following to 1 to enable a printk on each coreswitch. */
28 #define SSB_VERBOSE_PCICORESWITCH_DEBUG 0
31 /* Lowlevel coreswitching */
32 int ssb_pci_switch_coreidx(struct ssb_bus
*bus
, u8 coreidx
)
39 err
= pci_write_config_dword(bus
->host_pci
, SSB_BAR0_WIN
,
40 (coreidx
* SSB_CORE_SIZE
)
44 err
= pci_read_config_dword(bus
->host_pci
, SSB_BAR0_WIN
,
48 cur_core
= (cur_core
- SSB_ENUM_BASE
)
50 if (cur_core
== coreidx
)
53 if (attempts
++ > SSB_BAR0_MAX_RETRIES
)
59 pr_err("Failed to switch to core %u\n", coreidx
);
63 int ssb_pci_switch_core(struct ssb_bus
*bus
,
64 struct ssb_device
*dev
)
69 #if SSB_VERBOSE_PCICORESWITCH_DEBUG
70 pr_info("Switching to %s core, index %d\n",
71 ssb_core_name(dev
->id
.coreid
), dev
->core_index
);
74 spin_lock_irqsave(&bus
->bar_lock
, flags
);
75 err
= ssb_pci_switch_coreidx(bus
, dev
->core_index
);
77 bus
->mapped_device
= dev
;
78 spin_unlock_irqrestore(&bus
->bar_lock
, flags
);
83 /* Enable/disable the on board crystal oscillator and/or PLL. */
84 int ssb_pci_xtal(struct ssb_bus
*bus
, u32 what
, int turn_on
)
87 u32 in
, out
, outenable
;
90 if (bus
->bustype
!= SSB_BUSTYPE_PCI
)
93 err
= pci_read_config_dword(bus
->host_pci
, SSB_GPIO_IN
, &in
);
96 err
= pci_read_config_dword(bus
->host_pci
, SSB_GPIO_OUT
, &out
);
99 err
= pci_read_config_dword(bus
->host_pci
, SSB_GPIO_OUT_ENABLE
, &outenable
);
106 /* Avoid glitching the clock if GPRS is already using it.
107 * We can't actually read the state of the PLLPD so we infer it
108 * by the value of XTAL_PU which *is* readable via gpioin.
110 if (!(in
& SSB_GPIO_XTAL
)) {
111 if (what
& SSB_GPIO_XTAL
) {
112 /* Turn the crystal on */
113 out
|= SSB_GPIO_XTAL
;
114 if (what
& SSB_GPIO_PLL
)
116 err
= pci_write_config_dword(bus
->host_pci
, SSB_GPIO_OUT
, out
);
119 err
= pci_write_config_dword(bus
->host_pci
, SSB_GPIO_OUT_ENABLE
,
125 if (what
& SSB_GPIO_PLL
) {
126 /* Turn the PLL on */
127 out
&= ~SSB_GPIO_PLL
;
128 err
= pci_write_config_dword(bus
->host_pci
, SSB_GPIO_OUT
, out
);
135 err
= pci_read_config_word(bus
->host_pci
, PCI_STATUS
, &pci_status
);
138 pci_status
&= ~PCI_STATUS_SIG_TARGET_ABORT
;
139 err
= pci_write_config_word(bus
->host_pci
, PCI_STATUS
, pci_status
);
143 if (what
& SSB_GPIO_XTAL
) {
144 /* Turn the crystal off */
145 out
&= ~SSB_GPIO_XTAL
;
147 if (what
& SSB_GPIO_PLL
) {
148 /* Turn the PLL off */
151 err
= pci_write_config_dword(bus
->host_pci
, SSB_GPIO_OUT
, out
);
154 err
= pci_write_config_dword(bus
->host_pci
, SSB_GPIO_OUT_ENABLE
, outenable
);
163 pr_err("Error: ssb_pci_xtal() could not access PCI config space!\n");
168 /* Get the word-offset for a SSB_SPROM_XXX define. */
169 #define SPOFF(offset) ((offset) / sizeof(u16))
170 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
171 #define SPEX16(_outvar, _offset, _mask, _shift) \
172 out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
173 #define SPEX32(_outvar, _offset, _mask, _shift) \
174 out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
175 in[SPOFF(_offset)]) & (_mask)) >> (_shift))
176 #define SPEX(_outvar, _offset, _mask, _shift) \
177 SPEX16(_outvar, _offset, _mask, _shift)
179 #define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
181 SPEX(_field[0], _offset + 0, _mask, _shift); \
182 SPEX(_field[1], _offset + 2, _mask, _shift); \
183 SPEX(_field[2], _offset + 4, _mask, _shift); \
184 SPEX(_field[3], _offset + 6, _mask, _shift); \
185 SPEX(_field[4], _offset + 8, _mask, _shift); \
186 SPEX(_field[5], _offset + 10, _mask, _shift); \
187 SPEX(_field[6], _offset + 12, _mask, _shift); \
188 SPEX(_field[7], _offset + 14, _mask, _shift); \
192 static inline u8
ssb_crc8(u8 crc
, u8 data
)
194 /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
195 static const u8 t
[] = {
196 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
197 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
198 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
199 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
200 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
201 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
202 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
203 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
204 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
205 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
206 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
207 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
208 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
209 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
210 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
211 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
212 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
213 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
214 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
215 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
216 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
217 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
218 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
219 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
220 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
221 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
222 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
223 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
224 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
225 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
226 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
227 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
229 return t
[crc
^ data
];
232 static void sprom_get_mac(char *mac
, const u16
*in
)
235 for (i
= 0; i
< 3; i
++) {
241 static u8
ssb_sprom_crc(const u16
*sprom
, u16 size
)
246 for (word
= 0; word
< size
- 1; word
++) {
247 crc
= ssb_crc8(crc
, sprom
[word
] & 0x00FF);
248 crc
= ssb_crc8(crc
, (sprom
[word
] & 0xFF00) >> 8);
250 crc
= ssb_crc8(crc
, sprom
[size
- 1] & 0x00FF);
256 static int sprom_check_crc(const u16
*sprom
, size_t size
)
262 crc
= ssb_sprom_crc(sprom
, size
);
263 tmp
= sprom
[size
- 1] & SSB_SPROM_REVISION_CRC
;
264 expected_crc
= tmp
>> SSB_SPROM_REVISION_CRC_SHIFT
;
265 if (crc
!= expected_crc
)
271 static int sprom_do_read(struct ssb_bus
*bus
, u16
*sprom
)
275 for (i
= 0; i
< bus
->sprom_size
; i
++)
276 sprom
[i
] = ioread16(bus
->mmio
+ bus
->sprom_offset
+ (i
* 2));
281 static int sprom_do_write(struct ssb_bus
*bus
, const u16
*sprom
)
283 struct pci_dev
*pdev
= bus
->host_pci
;
286 u16 size
= bus
->sprom_size
;
288 pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
289 err
= pci_read_config_dword(pdev
, SSB_SPROMCTL
, &spromctl
);
292 spromctl
|= SSB_SPROMCTL_WE
;
293 err
= pci_write_config_dword(pdev
, SSB_SPROMCTL
, spromctl
);
298 for (i
= 0; i
< size
; i
++) {
301 else if (i
== size
/ 2)
303 else if (i
== (size
* 3) / 4)
307 writew(sprom
[i
], bus
->mmio
+ bus
->sprom_offset
+ (i
* 2));
311 err
= pci_read_config_dword(pdev
, SSB_SPROMCTL
, &spromctl
);
314 spromctl
&= ~SSB_SPROMCTL_WE
;
315 err
= pci_write_config_dword(pdev
, SSB_SPROMCTL
, spromctl
);
319 pr_cont("100%% ]\n");
320 pr_notice("SPROM written\n");
324 pr_err("Could not access SPROM control register.\n");
328 static s8
sprom_extract_antgain(u8 sprom_revision
, const u16
*in
, u16 offset
,
334 v
= in
[SPOFF(offset
)];
335 gain
= (v
& mask
) >> shift
;
337 gain
= 2; /* If unset use 2dBm */
338 if (sprom_revision
== 1) {
339 /* Convert to Q5.2 */
342 /* Q5.2 Fractional part is stored in 0xC0 */
343 gain
= ((gain
& 0xC0) >> 6) | ((gain
& 0x3F) << 2);
349 static void sprom_extract_r23(struct ssb_sprom
*out
, const u16
*in
)
351 SPEX(boardflags_hi
, SSB_SPROM2_BFLHI
, 0xFFFF, 0);
352 SPEX(opo
, SSB_SPROM2_OPO
, SSB_SPROM2_OPO_VALUE
, 0);
353 SPEX(pa1lob0
, SSB_SPROM2_PA1LOB0
, 0xFFFF, 0);
354 SPEX(pa1lob1
, SSB_SPROM2_PA1LOB1
, 0xFFFF, 0);
355 SPEX(pa1lob2
, SSB_SPROM2_PA1LOB2
, 0xFFFF, 0);
356 SPEX(pa1hib0
, SSB_SPROM2_PA1HIB0
, 0xFFFF, 0);
357 SPEX(pa1hib1
, SSB_SPROM2_PA1HIB1
, 0xFFFF, 0);
358 SPEX(pa1hib2
, SSB_SPROM2_PA1HIB2
, 0xFFFF, 0);
359 SPEX(maxpwr_ah
, SSB_SPROM2_MAXP_A
, SSB_SPROM2_MAXP_A_HI
, 0);
360 SPEX(maxpwr_al
, SSB_SPROM2_MAXP_A
, SSB_SPROM2_MAXP_A_LO
,
361 SSB_SPROM2_MAXP_A_LO_SHIFT
);
364 static void sprom_extract_r123(struct ssb_sprom
*out
, const u16
*in
)
368 if (out
->revision
== 3) /* rev 3 moved MAC */
369 loc
[0] = SSB_SPROM3_IL0MAC
;
371 loc
[0] = SSB_SPROM1_IL0MAC
;
372 loc
[1] = SSB_SPROM1_ET0MAC
;
373 loc
[2] = SSB_SPROM1_ET1MAC
;
375 sprom_get_mac(out
->il0mac
, &in
[SPOFF(loc
[0])]);
376 if (out
->revision
< 3) { /* only rev 1-2 have et0, et1 */
377 sprom_get_mac(out
->et0mac
, &in
[SPOFF(loc
[1])]);
378 sprom_get_mac(out
->et1mac
, &in
[SPOFF(loc
[2])]);
380 SPEX(et0phyaddr
, SSB_SPROM1_ETHPHY
, SSB_SPROM1_ETHPHY_ET0A
, 0);
381 SPEX(et1phyaddr
, SSB_SPROM1_ETHPHY
, SSB_SPROM1_ETHPHY_ET1A
,
382 SSB_SPROM1_ETHPHY_ET1A_SHIFT
);
383 SPEX(et0mdcport
, SSB_SPROM1_ETHPHY
, SSB_SPROM1_ETHPHY_ET0M
, 14);
384 SPEX(et1mdcport
, SSB_SPROM1_ETHPHY
, SSB_SPROM1_ETHPHY_ET1M
, 15);
385 SPEX(board_rev
, SSB_SPROM1_BINF
, SSB_SPROM1_BINF_BREV
, 0);
386 SPEX(board_type
, SSB_SPROM1_SPID
, 0xFFFF, 0);
387 if (out
->revision
== 1)
388 SPEX(country_code
, SSB_SPROM1_BINF
, SSB_SPROM1_BINF_CCODE
,
389 SSB_SPROM1_BINF_CCODE_SHIFT
);
390 SPEX(ant_available_a
, SSB_SPROM1_BINF
, SSB_SPROM1_BINF_ANTA
,
391 SSB_SPROM1_BINF_ANTA_SHIFT
);
392 SPEX(ant_available_bg
, SSB_SPROM1_BINF
, SSB_SPROM1_BINF_ANTBG
,
393 SSB_SPROM1_BINF_ANTBG_SHIFT
);
394 SPEX(pa0b0
, SSB_SPROM1_PA0B0
, 0xFFFF, 0);
395 SPEX(pa0b1
, SSB_SPROM1_PA0B1
, 0xFFFF, 0);
396 SPEX(pa0b2
, SSB_SPROM1_PA0B2
, 0xFFFF, 0);
397 SPEX(pa1b0
, SSB_SPROM1_PA1B0
, 0xFFFF, 0);
398 SPEX(pa1b1
, SSB_SPROM1_PA1B1
, 0xFFFF, 0);
399 SPEX(pa1b2
, SSB_SPROM1_PA1B2
, 0xFFFF, 0);
400 SPEX(gpio0
, SSB_SPROM1_GPIOA
, SSB_SPROM1_GPIOA_P0
, 0);
401 SPEX(gpio1
, SSB_SPROM1_GPIOA
, SSB_SPROM1_GPIOA_P1
,
402 SSB_SPROM1_GPIOA_P1_SHIFT
);
403 SPEX(gpio2
, SSB_SPROM1_GPIOB
, SSB_SPROM1_GPIOB_P2
, 0);
404 SPEX(gpio3
, SSB_SPROM1_GPIOB
, SSB_SPROM1_GPIOB_P3
,
405 SSB_SPROM1_GPIOB_P3_SHIFT
);
406 SPEX(maxpwr_a
, SSB_SPROM1_MAXPWR
, SSB_SPROM1_MAXPWR_A
,
407 SSB_SPROM1_MAXPWR_A_SHIFT
);
408 SPEX(maxpwr_bg
, SSB_SPROM1_MAXPWR
, SSB_SPROM1_MAXPWR_BG
, 0);
409 SPEX(itssi_a
, SSB_SPROM1_ITSSI
, SSB_SPROM1_ITSSI_A
,
410 SSB_SPROM1_ITSSI_A_SHIFT
);
411 SPEX(itssi_bg
, SSB_SPROM1_ITSSI
, SSB_SPROM1_ITSSI_BG
, 0);
412 SPEX(boardflags_lo
, SSB_SPROM1_BFLLO
, 0xFFFF, 0);
414 SPEX(alpha2
[0], SSB_SPROM1_CCODE
, 0xff00, 8);
415 SPEX(alpha2
[1], SSB_SPROM1_CCODE
, 0x00ff, 0);
417 /* Extract the antenna gain values. */
418 out
->antenna_gain
.a0
= sprom_extract_antgain(out
->revision
, in
,
421 SSB_SPROM1_AGAIN_BG_SHIFT
);
422 out
->antenna_gain
.a1
= sprom_extract_antgain(out
->revision
, in
,
425 SSB_SPROM1_AGAIN_A_SHIFT
);
426 if (out
->revision
>= 2)
427 sprom_extract_r23(out
, in
);
430 /* Revs 4 5 and 8 have partially shared layout */
431 static void sprom_extract_r458(struct ssb_sprom
*out
, const u16
*in
)
433 SPEX(txpid2g
[0], SSB_SPROM4_TXPID2G01
,
434 SSB_SPROM4_TXPID2G0
, SSB_SPROM4_TXPID2G0_SHIFT
);
435 SPEX(txpid2g
[1], SSB_SPROM4_TXPID2G01
,
436 SSB_SPROM4_TXPID2G1
, SSB_SPROM4_TXPID2G1_SHIFT
);
437 SPEX(txpid2g
[2], SSB_SPROM4_TXPID2G23
,
438 SSB_SPROM4_TXPID2G2
, SSB_SPROM4_TXPID2G2_SHIFT
);
439 SPEX(txpid2g
[3], SSB_SPROM4_TXPID2G23
,
440 SSB_SPROM4_TXPID2G3
, SSB_SPROM4_TXPID2G3_SHIFT
);
442 SPEX(txpid5gl
[0], SSB_SPROM4_TXPID5GL01
,
443 SSB_SPROM4_TXPID5GL0
, SSB_SPROM4_TXPID5GL0_SHIFT
);
444 SPEX(txpid5gl
[1], SSB_SPROM4_TXPID5GL01
,
445 SSB_SPROM4_TXPID5GL1
, SSB_SPROM4_TXPID5GL1_SHIFT
);
446 SPEX(txpid5gl
[2], SSB_SPROM4_TXPID5GL23
,
447 SSB_SPROM4_TXPID5GL2
, SSB_SPROM4_TXPID5GL2_SHIFT
);
448 SPEX(txpid5gl
[3], SSB_SPROM4_TXPID5GL23
,
449 SSB_SPROM4_TXPID5GL3
, SSB_SPROM4_TXPID5GL3_SHIFT
);
451 SPEX(txpid5g
[0], SSB_SPROM4_TXPID5G01
,
452 SSB_SPROM4_TXPID5G0
, SSB_SPROM4_TXPID5G0_SHIFT
);
453 SPEX(txpid5g
[1], SSB_SPROM4_TXPID5G01
,
454 SSB_SPROM4_TXPID5G1
, SSB_SPROM4_TXPID5G1_SHIFT
);
455 SPEX(txpid5g
[2], SSB_SPROM4_TXPID5G23
,
456 SSB_SPROM4_TXPID5G2
, SSB_SPROM4_TXPID5G2_SHIFT
);
457 SPEX(txpid5g
[3], SSB_SPROM4_TXPID5G23
,
458 SSB_SPROM4_TXPID5G3
, SSB_SPROM4_TXPID5G3_SHIFT
);
460 SPEX(txpid5gh
[0], SSB_SPROM4_TXPID5GH01
,
461 SSB_SPROM4_TXPID5GH0
, SSB_SPROM4_TXPID5GH0_SHIFT
);
462 SPEX(txpid5gh
[1], SSB_SPROM4_TXPID5GH01
,
463 SSB_SPROM4_TXPID5GH1
, SSB_SPROM4_TXPID5GH1_SHIFT
);
464 SPEX(txpid5gh
[2], SSB_SPROM4_TXPID5GH23
,
465 SSB_SPROM4_TXPID5GH2
, SSB_SPROM4_TXPID5GH2_SHIFT
);
466 SPEX(txpid5gh
[3], SSB_SPROM4_TXPID5GH23
,
467 SSB_SPROM4_TXPID5GH3
, SSB_SPROM4_TXPID5GH3_SHIFT
);
470 static void sprom_extract_r45(struct ssb_sprom
*out
, const u16
*in
)
472 static const u16 pwr_info_offset
[] = {
473 SSB_SPROM4_PWR_INFO_CORE0
, SSB_SPROM4_PWR_INFO_CORE1
,
474 SSB_SPROM4_PWR_INFO_CORE2
, SSB_SPROM4_PWR_INFO_CORE3
479 BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset
) !=
480 ARRAY_SIZE(out
->core_pwr_info
));
482 if (out
->revision
== 4)
483 il0mac_offset
= SSB_SPROM4_IL0MAC
;
485 il0mac_offset
= SSB_SPROM5_IL0MAC
;
487 sprom_get_mac(out
->il0mac
, &in
[SPOFF(il0mac_offset
)]);
489 SPEX(et0phyaddr
, SSB_SPROM4_ETHPHY
, SSB_SPROM4_ETHPHY_ET0A
, 0);
490 SPEX(et1phyaddr
, SSB_SPROM4_ETHPHY
, SSB_SPROM4_ETHPHY_ET1A
,
491 SSB_SPROM4_ETHPHY_ET1A_SHIFT
);
492 SPEX(board_rev
, SSB_SPROM4_BOARDREV
, 0xFFFF, 0);
493 SPEX(board_type
, SSB_SPROM1_SPID
, 0xFFFF, 0);
494 if (out
->revision
== 4) {
495 SPEX(alpha2
[0], SSB_SPROM4_CCODE
, 0xff00, 8);
496 SPEX(alpha2
[1], SSB_SPROM4_CCODE
, 0x00ff, 0);
497 SPEX(boardflags_lo
, SSB_SPROM4_BFLLO
, 0xFFFF, 0);
498 SPEX(boardflags_hi
, SSB_SPROM4_BFLHI
, 0xFFFF, 0);
499 SPEX(boardflags2_lo
, SSB_SPROM4_BFL2LO
, 0xFFFF, 0);
500 SPEX(boardflags2_hi
, SSB_SPROM4_BFL2HI
, 0xFFFF, 0);
502 SPEX(alpha2
[0], SSB_SPROM5_CCODE
, 0xff00, 8);
503 SPEX(alpha2
[1], SSB_SPROM5_CCODE
, 0x00ff, 0);
504 SPEX(boardflags_lo
, SSB_SPROM5_BFLLO
, 0xFFFF, 0);
505 SPEX(boardflags_hi
, SSB_SPROM5_BFLHI
, 0xFFFF, 0);
506 SPEX(boardflags2_lo
, SSB_SPROM5_BFL2LO
, 0xFFFF, 0);
507 SPEX(boardflags2_hi
, SSB_SPROM5_BFL2HI
, 0xFFFF, 0);
509 SPEX(ant_available_a
, SSB_SPROM4_ANTAVAIL
, SSB_SPROM4_ANTAVAIL_A
,
510 SSB_SPROM4_ANTAVAIL_A_SHIFT
);
511 SPEX(ant_available_bg
, SSB_SPROM4_ANTAVAIL
, SSB_SPROM4_ANTAVAIL_BG
,
512 SSB_SPROM4_ANTAVAIL_BG_SHIFT
);
513 SPEX(maxpwr_bg
, SSB_SPROM4_MAXP_BG
, SSB_SPROM4_MAXP_BG_MASK
, 0);
514 SPEX(itssi_bg
, SSB_SPROM4_MAXP_BG
, SSB_SPROM4_ITSSI_BG
,
515 SSB_SPROM4_ITSSI_BG_SHIFT
);
516 SPEX(maxpwr_a
, SSB_SPROM4_MAXP_A
, SSB_SPROM4_MAXP_A_MASK
, 0);
517 SPEX(itssi_a
, SSB_SPROM4_MAXP_A
, SSB_SPROM4_ITSSI_A
,
518 SSB_SPROM4_ITSSI_A_SHIFT
);
519 if (out
->revision
== 4) {
520 SPEX(gpio0
, SSB_SPROM4_GPIOA
, SSB_SPROM4_GPIOA_P0
, 0);
521 SPEX(gpio1
, SSB_SPROM4_GPIOA
, SSB_SPROM4_GPIOA_P1
,
522 SSB_SPROM4_GPIOA_P1_SHIFT
);
523 SPEX(gpio2
, SSB_SPROM4_GPIOB
, SSB_SPROM4_GPIOB_P2
, 0);
524 SPEX(gpio3
, SSB_SPROM4_GPIOB
, SSB_SPROM4_GPIOB_P3
,
525 SSB_SPROM4_GPIOB_P3_SHIFT
);
527 SPEX(gpio0
, SSB_SPROM5_GPIOA
, SSB_SPROM5_GPIOA_P0
, 0);
528 SPEX(gpio1
, SSB_SPROM5_GPIOA
, SSB_SPROM5_GPIOA_P1
,
529 SSB_SPROM5_GPIOA_P1_SHIFT
);
530 SPEX(gpio2
, SSB_SPROM5_GPIOB
, SSB_SPROM5_GPIOB_P2
, 0);
531 SPEX(gpio3
, SSB_SPROM5_GPIOB
, SSB_SPROM5_GPIOB_P3
,
532 SSB_SPROM5_GPIOB_P3_SHIFT
);
535 /* Extract the antenna gain values. */
536 out
->antenna_gain
.a0
= sprom_extract_antgain(out
->revision
, in
,
539 SSB_SPROM4_AGAIN0_SHIFT
);
540 out
->antenna_gain
.a1
= sprom_extract_antgain(out
->revision
, in
,
543 SSB_SPROM4_AGAIN1_SHIFT
);
544 out
->antenna_gain
.a2
= sprom_extract_antgain(out
->revision
, in
,
547 SSB_SPROM4_AGAIN2_SHIFT
);
548 out
->antenna_gain
.a3
= sprom_extract_antgain(out
->revision
, in
,
551 SSB_SPROM4_AGAIN3_SHIFT
);
553 /* Extract cores power info info */
554 for (i
= 0; i
< ARRAY_SIZE(pwr_info_offset
); i
++) {
555 u16 o
= pwr_info_offset
[i
];
557 SPEX(core_pwr_info
[i
].itssi_2g
, o
+ SSB_SPROM4_2G_MAXP_ITSSI
,
558 SSB_SPROM4_2G_ITSSI
, SSB_SPROM4_2G_ITSSI_SHIFT
);
559 SPEX(core_pwr_info
[i
].maxpwr_2g
, o
+ SSB_SPROM4_2G_MAXP_ITSSI
,
560 SSB_SPROM4_2G_MAXP
, 0);
562 SPEX(core_pwr_info
[i
].pa_2g
[0], o
+ SSB_SPROM4_2G_PA_0
, ~0, 0);
563 SPEX(core_pwr_info
[i
].pa_2g
[1], o
+ SSB_SPROM4_2G_PA_1
, ~0, 0);
564 SPEX(core_pwr_info
[i
].pa_2g
[2], o
+ SSB_SPROM4_2G_PA_2
, ~0, 0);
565 SPEX(core_pwr_info
[i
].pa_2g
[3], o
+ SSB_SPROM4_2G_PA_3
, ~0, 0);
567 SPEX(core_pwr_info
[i
].itssi_5g
, o
+ SSB_SPROM4_5G_MAXP_ITSSI
,
568 SSB_SPROM4_5G_ITSSI
, SSB_SPROM4_5G_ITSSI_SHIFT
);
569 SPEX(core_pwr_info
[i
].maxpwr_5g
, o
+ SSB_SPROM4_5G_MAXP_ITSSI
,
570 SSB_SPROM4_5G_MAXP
, 0);
571 SPEX(core_pwr_info
[i
].maxpwr_5gh
, o
+ SSB_SPROM4_5GHL_MAXP
,
572 SSB_SPROM4_5GH_MAXP
, 0);
573 SPEX(core_pwr_info
[i
].maxpwr_5gl
, o
+ SSB_SPROM4_5GHL_MAXP
,
574 SSB_SPROM4_5GL_MAXP
, SSB_SPROM4_5GL_MAXP_SHIFT
);
576 SPEX(core_pwr_info
[i
].pa_5gl
[0], o
+ SSB_SPROM4_5GL_PA_0
, ~0, 0);
577 SPEX(core_pwr_info
[i
].pa_5gl
[1], o
+ SSB_SPROM4_5GL_PA_1
, ~0, 0);
578 SPEX(core_pwr_info
[i
].pa_5gl
[2], o
+ SSB_SPROM4_5GL_PA_2
, ~0, 0);
579 SPEX(core_pwr_info
[i
].pa_5gl
[3], o
+ SSB_SPROM4_5GL_PA_3
, ~0, 0);
580 SPEX(core_pwr_info
[i
].pa_5g
[0], o
+ SSB_SPROM4_5G_PA_0
, ~0, 0);
581 SPEX(core_pwr_info
[i
].pa_5g
[1], o
+ SSB_SPROM4_5G_PA_1
, ~0, 0);
582 SPEX(core_pwr_info
[i
].pa_5g
[2], o
+ SSB_SPROM4_5G_PA_2
, ~0, 0);
583 SPEX(core_pwr_info
[i
].pa_5g
[3], o
+ SSB_SPROM4_5G_PA_3
, ~0, 0);
584 SPEX(core_pwr_info
[i
].pa_5gh
[0], o
+ SSB_SPROM4_5GH_PA_0
, ~0, 0);
585 SPEX(core_pwr_info
[i
].pa_5gh
[1], o
+ SSB_SPROM4_5GH_PA_1
, ~0, 0);
586 SPEX(core_pwr_info
[i
].pa_5gh
[2], o
+ SSB_SPROM4_5GH_PA_2
, ~0, 0);
587 SPEX(core_pwr_info
[i
].pa_5gh
[3], o
+ SSB_SPROM4_5GH_PA_3
, ~0, 0);
590 sprom_extract_r458(out
, in
);
592 /* TODO - get remaining rev 4 stuff needed */
595 static void sprom_extract_r8(struct ssb_sprom
*out
, const u16
*in
)
599 u16 pwr_info_offset
[] = {
600 SSB_SROM8_PWR_INFO_CORE0
, SSB_SROM8_PWR_INFO_CORE1
,
601 SSB_SROM8_PWR_INFO_CORE2
, SSB_SROM8_PWR_INFO_CORE3
603 BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset
) !=
604 ARRAY_SIZE(out
->core_pwr_info
));
606 /* extract the MAC address */
607 sprom_get_mac(out
->il0mac
, &in
[SPOFF(SSB_SPROM8_IL0MAC
)]);
609 SPEX(board_rev
, SSB_SPROM8_BOARDREV
, 0xFFFF, 0);
610 SPEX(board_type
, SSB_SPROM1_SPID
, 0xFFFF, 0);
611 SPEX(alpha2
[0], SSB_SPROM8_CCODE
, 0xff00, 8);
612 SPEX(alpha2
[1], SSB_SPROM8_CCODE
, 0x00ff, 0);
613 SPEX(boardflags_lo
, SSB_SPROM8_BFLLO
, 0xFFFF, 0);
614 SPEX(boardflags_hi
, SSB_SPROM8_BFLHI
, 0xFFFF, 0);
615 SPEX(boardflags2_lo
, SSB_SPROM8_BFL2LO
, 0xFFFF, 0);
616 SPEX(boardflags2_hi
, SSB_SPROM8_BFL2HI
, 0xFFFF, 0);
617 SPEX(ant_available_a
, SSB_SPROM8_ANTAVAIL
, SSB_SPROM8_ANTAVAIL_A
,
618 SSB_SPROM8_ANTAVAIL_A_SHIFT
);
619 SPEX(ant_available_bg
, SSB_SPROM8_ANTAVAIL
, SSB_SPROM8_ANTAVAIL_BG
,
620 SSB_SPROM8_ANTAVAIL_BG_SHIFT
);
621 SPEX(maxpwr_bg
, SSB_SPROM8_MAXP_BG
, SSB_SPROM8_MAXP_BG_MASK
, 0);
622 SPEX(itssi_bg
, SSB_SPROM8_MAXP_BG
, SSB_SPROM8_ITSSI_BG
,
623 SSB_SPROM8_ITSSI_BG_SHIFT
);
624 SPEX(maxpwr_a
, SSB_SPROM8_MAXP_A
, SSB_SPROM8_MAXP_A_MASK
, 0);
625 SPEX(itssi_a
, SSB_SPROM8_MAXP_A
, SSB_SPROM8_ITSSI_A
,
626 SSB_SPROM8_ITSSI_A_SHIFT
);
627 SPEX(maxpwr_ah
, SSB_SPROM8_MAXP_AHL
, SSB_SPROM8_MAXP_AH_MASK
, 0);
628 SPEX(maxpwr_al
, SSB_SPROM8_MAXP_AHL
, SSB_SPROM8_MAXP_AL_MASK
,
629 SSB_SPROM8_MAXP_AL_SHIFT
);
630 SPEX(gpio0
, SSB_SPROM8_GPIOA
, SSB_SPROM8_GPIOA_P0
, 0);
631 SPEX(gpio1
, SSB_SPROM8_GPIOA
, SSB_SPROM8_GPIOA_P1
,
632 SSB_SPROM8_GPIOA_P1_SHIFT
);
633 SPEX(gpio2
, SSB_SPROM8_GPIOB
, SSB_SPROM8_GPIOB_P2
, 0);
634 SPEX(gpio3
, SSB_SPROM8_GPIOB
, SSB_SPROM8_GPIOB_P3
,
635 SSB_SPROM8_GPIOB_P3_SHIFT
);
636 SPEX(tri2g
, SSB_SPROM8_TRI25G
, SSB_SPROM8_TRI2G
, 0);
637 SPEX(tri5g
, SSB_SPROM8_TRI25G
, SSB_SPROM8_TRI5G
,
638 SSB_SPROM8_TRI5G_SHIFT
);
639 SPEX(tri5gl
, SSB_SPROM8_TRI5GHL
, SSB_SPROM8_TRI5GL
, 0);
640 SPEX(tri5gh
, SSB_SPROM8_TRI5GHL
, SSB_SPROM8_TRI5GH
,
641 SSB_SPROM8_TRI5GH_SHIFT
);
642 SPEX(rxpo2g
, SSB_SPROM8_RXPO
, SSB_SPROM8_RXPO2G
, 0);
643 SPEX(rxpo5g
, SSB_SPROM8_RXPO
, SSB_SPROM8_RXPO5G
,
644 SSB_SPROM8_RXPO5G_SHIFT
);
645 SPEX(rssismf2g
, SSB_SPROM8_RSSIPARM2G
, SSB_SPROM8_RSSISMF2G
, 0);
646 SPEX(rssismc2g
, SSB_SPROM8_RSSIPARM2G
, SSB_SPROM8_RSSISMC2G
,
647 SSB_SPROM8_RSSISMC2G_SHIFT
);
648 SPEX(rssisav2g
, SSB_SPROM8_RSSIPARM2G
, SSB_SPROM8_RSSISAV2G
,
649 SSB_SPROM8_RSSISAV2G_SHIFT
);
650 SPEX(bxa2g
, SSB_SPROM8_RSSIPARM2G
, SSB_SPROM8_BXA2G
,
651 SSB_SPROM8_BXA2G_SHIFT
);
652 SPEX(rssismf5g
, SSB_SPROM8_RSSIPARM5G
, SSB_SPROM8_RSSISMF5G
, 0);
653 SPEX(rssismc5g
, SSB_SPROM8_RSSIPARM5G
, SSB_SPROM8_RSSISMC5G
,
654 SSB_SPROM8_RSSISMC5G_SHIFT
);
655 SPEX(rssisav5g
, SSB_SPROM8_RSSIPARM5G
, SSB_SPROM8_RSSISAV5G
,
656 SSB_SPROM8_RSSISAV5G_SHIFT
);
657 SPEX(bxa5g
, SSB_SPROM8_RSSIPARM5G
, SSB_SPROM8_BXA5G
,
658 SSB_SPROM8_BXA5G_SHIFT
);
659 SPEX(pa0b0
, SSB_SPROM8_PA0B0
, 0xFFFF, 0);
660 SPEX(pa0b1
, SSB_SPROM8_PA0B1
, 0xFFFF, 0);
661 SPEX(pa0b2
, SSB_SPROM8_PA0B2
, 0xFFFF, 0);
662 SPEX(pa1b0
, SSB_SPROM8_PA1B0
, 0xFFFF, 0);
663 SPEX(pa1b1
, SSB_SPROM8_PA1B1
, 0xFFFF, 0);
664 SPEX(pa1b2
, SSB_SPROM8_PA1B2
, 0xFFFF, 0);
665 SPEX(pa1lob0
, SSB_SPROM8_PA1LOB0
, 0xFFFF, 0);
666 SPEX(pa1lob1
, SSB_SPROM8_PA1LOB1
, 0xFFFF, 0);
667 SPEX(pa1lob2
, SSB_SPROM8_PA1LOB2
, 0xFFFF, 0);
668 SPEX(pa1hib0
, SSB_SPROM8_PA1HIB0
, 0xFFFF, 0);
669 SPEX(pa1hib1
, SSB_SPROM8_PA1HIB1
, 0xFFFF, 0);
670 SPEX(pa1hib2
, SSB_SPROM8_PA1HIB2
, 0xFFFF, 0);
671 SPEX(cck2gpo
, SSB_SPROM8_CCK2GPO
, 0xFFFF, 0);
672 SPEX32(ofdm2gpo
, SSB_SPROM8_OFDM2GPO
, 0xFFFFFFFF, 0);
673 SPEX32(ofdm5glpo
, SSB_SPROM8_OFDM5GLPO
, 0xFFFFFFFF, 0);
674 SPEX32(ofdm5gpo
, SSB_SPROM8_OFDM5GPO
, 0xFFFFFFFF, 0);
675 SPEX32(ofdm5ghpo
, SSB_SPROM8_OFDM5GHPO
, 0xFFFFFFFF, 0);
677 /* Extract the antenna gain values. */
678 out
->antenna_gain
.a0
= sprom_extract_antgain(out
->revision
, in
,
681 SSB_SPROM8_AGAIN0_SHIFT
);
682 out
->antenna_gain
.a1
= sprom_extract_antgain(out
->revision
, in
,
685 SSB_SPROM8_AGAIN1_SHIFT
);
686 out
->antenna_gain
.a2
= sprom_extract_antgain(out
->revision
, in
,
689 SSB_SPROM8_AGAIN2_SHIFT
);
690 out
->antenna_gain
.a3
= sprom_extract_antgain(out
->revision
, in
,
693 SSB_SPROM8_AGAIN3_SHIFT
);
695 /* Extract cores power info info */
696 for (i
= 0; i
< ARRAY_SIZE(pwr_info_offset
); i
++) {
697 o
= pwr_info_offset
[i
];
698 SPEX(core_pwr_info
[i
].itssi_2g
, o
+ SSB_SROM8_2G_MAXP_ITSSI
,
699 SSB_SPROM8_2G_ITSSI
, SSB_SPROM8_2G_ITSSI_SHIFT
);
700 SPEX(core_pwr_info
[i
].maxpwr_2g
, o
+ SSB_SROM8_2G_MAXP_ITSSI
,
701 SSB_SPROM8_2G_MAXP
, 0);
703 SPEX(core_pwr_info
[i
].pa_2g
[0], o
+ SSB_SROM8_2G_PA_0
, ~0, 0);
704 SPEX(core_pwr_info
[i
].pa_2g
[1], o
+ SSB_SROM8_2G_PA_1
, ~0, 0);
705 SPEX(core_pwr_info
[i
].pa_2g
[2], o
+ SSB_SROM8_2G_PA_2
, ~0, 0);
707 SPEX(core_pwr_info
[i
].itssi_5g
, o
+ SSB_SROM8_5G_MAXP_ITSSI
,
708 SSB_SPROM8_5G_ITSSI
, SSB_SPROM8_5G_ITSSI_SHIFT
);
709 SPEX(core_pwr_info
[i
].maxpwr_5g
, o
+ SSB_SROM8_5G_MAXP_ITSSI
,
710 SSB_SPROM8_5G_MAXP
, 0);
711 SPEX(core_pwr_info
[i
].maxpwr_5gh
, o
+ SSB_SPROM8_5GHL_MAXP
,
712 SSB_SPROM8_5GH_MAXP
, 0);
713 SPEX(core_pwr_info
[i
].maxpwr_5gl
, o
+ SSB_SPROM8_5GHL_MAXP
,
714 SSB_SPROM8_5GL_MAXP
, SSB_SPROM8_5GL_MAXP_SHIFT
);
716 SPEX(core_pwr_info
[i
].pa_5gl
[0], o
+ SSB_SROM8_5GL_PA_0
, ~0, 0);
717 SPEX(core_pwr_info
[i
].pa_5gl
[1], o
+ SSB_SROM8_5GL_PA_1
, ~0, 0);
718 SPEX(core_pwr_info
[i
].pa_5gl
[2], o
+ SSB_SROM8_5GL_PA_2
, ~0, 0);
719 SPEX(core_pwr_info
[i
].pa_5g
[0], o
+ SSB_SROM8_5G_PA_0
, ~0, 0);
720 SPEX(core_pwr_info
[i
].pa_5g
[1], o
+ SSB_SROM8_5G_PA_1
, ~0, 0);
721 SPEX(core_pwr_info
[i
].pa_5g
[2], o
+ SSB_SROM8_5G_PA_2
, ~0, 0);
722 SPEX(core_pwr_info
[i
].pa_5gh
[0], o
+ SSB_SROM8_5GH_PA_0
, ~0, 0);
723 SPEX(core_pwr_info
[i
].pa_5gh
[1], o
+ SSB_SROM8_5GH_PA_1
, ~0, 0);
724 SPEX(core_pwr_info
[i
].pa_5gh
[2], o
+ SSB_SROM8_5GH_PA_2
, ~0, 0);
727 /* Extract FEM info */
728 SPEX(fem
.ghz2
.tssipos
, SSB_SPROM8_FEM2G
,
729 SSB_SROM8_FEM_TSSIPOS
, SSB_SROM8_FEM_TSSIPOS_SHIFT
);
730 SPEX(fem
.ghz2
.extpa_gain
, SSB_SPROM8_FEM2G
,
731 SSB_SROM8_FEM_EXTPA_GAIN
, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT
);
732 SPEX(fem
.ghz2
.pdet_range
, SSB_SPROM8_FEM2G
,
733 SSB_SROM8_FEM_PDET_RANGE
, SSB_SROM8_FEM_PDET_RANGE_SHIFT
);
734 SPEX(fem
.ghz2
.tr_iso
, SSB_SPROM8_FEM2G
,
735 SSB_SROM8_FEM_TR_ISO
, SSB_SROM8_FEM_TR_ISO_SHIFT
);
736 SPEX(fem
.ghz2
.antswlut
, SSB_SPROM8_FEM2G
,
737 SSB_SROM8_FEM_ANTSWLUT
, SSB_SROM8_FEM_ANTSWLUT_SHIFT
);
739 SPEX(fem
.ghz5
.tssipos
, SSB_SPROM8_FEM5G
,
740 SSB_SROM8_FEM_TSSIPOS
, SSB_SROM8_FEM_TSSIPOS_SHIFT
);
741 SPEX(fem
.ghz5
.extpa_gain
, SSB_SPROM8_FEM5G
,
742 SSB_SROM8_FEM_EXTPA_GAIN
, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT
);
743 SPEX(fem
.ghz5
.pdet_range
, SSB_SPROM8_FEM5G
,
744 SSB_SROM8_FEM_PDET_RANGE
, SSB_SROM8_FEM_PDET_RANGE_SHIFT
);
745 SPEX(fem
.ghz5
.tr_iso
, SSB_SPROM8_FEM5G
,
746 SSB_SROM8_FEM_TR_ISO
, SSB_SROM8_FEM_TR_ISO_SHIFT
);
747 SPEX(fem
.ghz5
.antswlut
, SSB_SPROM8_FEM5G
,
748 SSB_SROM8_FEM_ANTSWLUT
, SSB_SROM8_FEM_ANTSWLUT_SHIFT
);
750 SPEX(leddc_on_time
, SSB_SPROM8_LEDDC
, SSB_SPROM8_LEDDC_ON
,
751 SSB_SPROM8_LEDDC_ON_SHIFT
);
752 SPEX(leddc_off_time
, SSB_SPROM8_LEDDC
, SSB_SPROM8_LEDDC_OFF
,
753 SSB_SPROM8_LEDDC_OFF_SHIFT
);
755 SPEX(txchain
, SSB_SPROM8_TXRXC
, SSB_SPROM8_TXRXC_TXCHAIN
,
756 SSB_SPROM8_TXRXC_TXCHAIN_SHIFT
);
757 SPEX(rxchain
, SSB_SPROM8_TXRXC
, SSB_SPROM8_TXRXC_RXCHAIN
,
758 SSB_SPROM8_TXRXC_RXCHAIN_SHIFT
);
759 SPEX(antswitch
, SSB_SPROM8_TXRXC
, SSB_SPROM8_TXRXC_SWITCH
,
760 SSB_SPROM8_TXRXC_SWITCH_SHIFT
);
762 SPEX(opo
, SSB_SPROM8_OFDM2GPO
, 0x00ff, 0);
764 SPEX_ARRAY8(mcs2gpo
, SSB_SPROM8_2G_MCSPO
, ~0, 0);
765 SPEX_ARRAY8(mcs5gpo
, SSB_SPROM8_5G_MCSPO
, ~0, 0);
766 SPEX_ARRAY8(mcs5glpo
, SSB_SPROM8_5GL_MCSPO
, ~0, 0);
767 SPEX_ARRAY8(mcs5ghpo
, SSB_SPROM8_5GH_MCSPO
, ~0, 0);
769 SPEX(rawtempsense
, SSB_SPROM8_RAWTS
, SSB_SPROM8_RAWTS_RAWTEMP
,
770 SSB_SPROM8_RAWTS_RAWTEMP_SHIFT
);
771 SPEX(measpower
, SSB_SPROM8_RAWTS
, SSB_SPROM8_RAWTS_MEASPOWER
,
772 SSB_SPROM8_RAWTS_MEASPOWER_SHIFT
);
773 SPEX(tempsense_slope
, SSB_SPROM8_OPT_CORRX
,
774 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE
,
775 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT
);
776 SPEX(tempcorrx
, SSB_SPROM8_OPT_CORRX
, SSB_SPROM8_OPT_CORRX_TEMPCORRX
,
777 SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT
);
778 SPEX(tempsense_option
, SSB_SPROM8_OPT_CORRX
,
779 SSB_SPROM8_OPT_CORRX_TEMP_OPTION
,
780 SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT
);
781 SPEX(freqoffset_corr
, SSB_SPROM8_HWIQ_IQSWP
,
782 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR
,
783 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT
);
784 SPEX(iqcal_swp_dis
, SSB_SPROM8_HWIQ_IQSWP
,
785 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP
,
786 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT
);
787 SPEX(hw_iqcal_en
, SSB_SPROM8_HWIQ_IQSWP
, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL
,
788 SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT
);
790 SPEX(bw40po
, SSB_SPROM8_BW40PO
, ~0, 0);
791 SPEX(cddpo
, SSB_SPROM8_CDDPO
, ~0, 0);
792 SPEX(stbcpo
, SSB_SPROM8_STBCPO
, ~0, 0);
793 SPEX(bwduppo
, SSB_SPROM8_BWDUPPO
, ~0, 0);
795 SPEX(tempthresh
, SSB_SPROM8_THERMAL
, SSB_SPROM8_THERMAL_TRESH
,
796 SSB_SPROM8_THERMAL_TRESH_SHIFT
);
797 SPEX(tempoffset
, SSB_SPROM8_THERMAL
, SSB_SPROM8_THERMAL_OFFSET
,
798 SSB_SPROM8_THERMAL_OFFSET_SHIFT
);
799 SPEX(phycal_tempdelta
, SSB_SPROM8_TEMPDELTA
,
800 SSB_SPROM8_TEMPDELTA_PHYCAL
,
801 SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT
);
802 SPEX(temps_period
, SSB_SPROM8_TEMPDELTA
, SSB_SPROM8_TEMPDELTA_PERIOD
,
803 SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT
);
804 SPEX(temps_hysteresis
, SSB_SPROM8_TEMPDELTA
,
805 SSB_SPROM8_TEMPDELTA_HYSTERESIS
,
806 SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT
);
807 sprom_extract_r458(out
, in
);
809 /* TODO - get remaining rev 8 stuff needed */
812 static int sprom_extract(struct ssb_bus
*bus
, struct ssb_sprom
*out
,
813 const u16
*in
, u16 size
)
815 memset(out
, 0, sizeof(*out
));
817 out
->revision
= in
[size
- 1] & 0x00FF;
818 pr_debug("SPROM revision %d detected\n", out
->revision
);
819 memset(out
->et0mac
, 0xFF, 6); /* preset et0 and et1 mac */
820 memset(out
->et1mac
, 0xFF, 6);
822 if ((bus
->chip_id
& 0xFF00) == 0x4400) {
823 /* Workaround: The BCM44XX chip has a stupid revision
824 * number stored in the SPROM.
825 * Always extract r1. */
827 pr_debug("SPROM treated as revision %d\n", out
->revision
);
830 switch (out
->revision
) {
834 sprom_extract_r123(out
, in
);
838 sprom_extract_r45(out
, in
);
841 sprom_extract_r8(out
, in
);
844 pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
847 sprom_extract_r123(out
, in
);
850 if (out
->boardflags_lo
== 0xFFFF)
851 out
->boardflags_lo
= 0; /* per specs */
852 if (out
->boardflags_hi
== 0xFFFF)
853 out
->boardflags_hi
= 0; /* per specs */
858 static int ssb_pci_sprom_get(struct ssb_bus
*bus
,
859 struct ssb_sprom
*sprom
)
864 if (!ssb_is_sprom_available(bus
)) {
865 pr_err("No SPROM available!\n");
868 if (bus
->chipco
.dev
) { /* can be unavailable! */
870 * get SPROM offset: SSB_SPROM_BASE1 except for
871 * chipcommon rev >= 31 or chip ID is 0x4312 and
872 * chipcommon status & 3 == 2
874 if (bus
->chipco
.dev
->id
.revision
>= 31)
875 bus
->sprom_offset
= SSB_SPROM_BASE31
;
876 else if (bus
->chip_id
== 0x4312 &&
877 (bus
->chipco
.status
& 0x03) == 2)
878 bus
->sprom_offset
= SSB_SPROM_BASE31
;
880 bus
->sprom_offset
= SSB_SPROM_BASE1
;
882 bus
->sprom_offset
= SSB_SPROM_BASE1
;
884 pr_debug("SPROM offset is 0x%x\n", bus
->sprom_offset
);
886 buf
= kcalloc(SSB_SPROMSIZE_WORDS_R123
, sizeof(u16
), GFP_KERNEL
);
889 bus
->sprom_size
= SSB_SPROMSIZE_WORDS_R123
;
890 sprom_do_read(bus
, buf
);
891 err
= sprom_check_crc(buf
, bus
->sprom_size
);
893 /* try for a 440 byte SPROM - revision 4 and higher */
895 buf
= kcalloc(SSB_SPROMSIZE_WORDS_R4
, sizeof(u16
),
899 bus
->sprom_size
= SSB_SPROMSIZE_WORDS_R4
;
900 sprom_do_read(bus
, buf
);
901 err
= sprom_check_crc(buf
, bus
->sprom_size
);
903 /* All CRC attempts failed.
904 * Maybe there is no SPROM on the device?
905 * Now we ask the arch code if there is some sprom
906 * available for this device in some other storage */
907 err
= ssb_fill_sprom_with_fallback(bus
, sprom
);
909 pr_warn("WARNING: Using fallback SPROM failed (err %d)\n",
913 pr_debug("Using SPROM revision %d provided by platform\n",
918 pr_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
921 err
= sprom_extract(bus
, sprom
, buf
, bus
->sprom_size
);
928 static void ssb_pci_get_boardinfo(struct ssb_bus
*bus
,
929 struct ssb_boardinfo
*bi
)
931 bi
->vendor
= bus
->host_pci
->subsystem_vendor
;
932 bi
->type
= bus
->host_pci
->subsystem_device
;
935 int ssb_pci_get_invariants(struct ssb_bus
*bus
,
936 struct ssb_init_invariants
*iv
)
940 err
= ssb_pci_sprom_get(bus
, &iv
->sprom
);
943 ssb_pci_get_boardinfo(bus
, &iv
->boardinfo
);
949 static int ssb_pci_assert_buspower(struct ssb_bus
*bus
)
951 if (likely(bus
->powered_up
))
954 pr_err("FATAL ERROR: Bus powered down while accessing PCI MMIO space\n");
955 if (bus
->power_warn_count
<= 10) {
956 bus
->power_warn_count
++;
963 static u8
ssb_pci_read8(struct ssb_device
*dev
, u16 offset
)
965 struct ssb_bus
*bus
= dev
->bus
;
967 if (unlikely(ssb_pci_assert_buspower(bus
)))
969 if (unlikely(bus
->mapped_device
!= dev
)) {
970 if (unlikely(ssb_pci_switch_core(bus
, dev
)))
973 return ioread8(bus
->mmio
+ offset
);
976 static u16
ssb_pci_read16(struct ssb_device
*dev
, u16 offset
)
978 struct ssb_bus
*bus
= dev
->bus
;
980 if (unlikely(ssb_pci_assert_buspower(bus
)))
982 if (unlikely(bus
->mapped_device
!= dev
)) {
983 if (unlikely(ssb_pci_switch_core(bus
, dev
)))
986 return ioread16(bus
->mmio
+ offset
);
989 static u32
ssb_pci_read32(struct ssb_device
*dev
, u16 offset
)
991 struct ssb_bus
*bus
= dev
->bus
;
993 if (unlikely(ssb_pci_assert_buspower(bus
)))
995 if (unlikely(bus
->mapped_device
!= dev
)) {
996 if (unlikely(ssb_pci_switch_core(bus
, dev
)))
999 return ioread32(bus
->mmio
+ offset
);
1002 #ifdef CONFIG_SSB_BLOCKIO
1003 static void ssb_pci_block_read(struct ssb_device
*dev
, void *buffer
,
1004 size_t count
, u16 offset
, u8 reg_width
)
1006 struct ssb_bus
*bus
= dev
->bus
;
1007 void __iomem
*addr
= bus
->mmio
+ offset
;
1009 if (unlikely(ssb_pci_assert_buspower(bus
)))
1011 if (unlikely(bus
->mapped_device
!= dev
)) {
1012 if (unlikely(ssb_pci_switch_core(bus
, dev
)))
1015 switch (reg_width
) {
1017 ioread8_rep(addr
, buffer
, count
);
1021 ioread16_rep(addr
, buffer
, count
>> 1);
1025 ioread32_rep(addr
, buffer
, count
>> 2);
1033 memset(buffer
, 0xFF, count
);
1035 #endif /* CONFIG_SSB_BLOCKIO */
1037 static void ssb_pci_write8(struct ssb_device
*dev
, u16 offset
, u8 value
)
1039 struct ssb_bus
*bus
= dev
->bus
;
1041 if (unlikely(ssb_pci_assert_buspower(bus
)))
1043 if (unlikely(bus
->mapped_device
!= dev
)) {
1044 if (unlikely(ssb_pci_switch_core(bus
, dev
)))
1047 iowrite8(value
, bus
->mmio
+ offset
);
1050 static void ssb_pci_write16(struct ssb_device
*dev
, u16 offset
, u16 value
)
1052 struct ssb_bus
*bus
= dev
->bus
;
1054 if (unlikely(ssb_pci_assert_buspower(bus
)))
1056 if (unlikely(bus
->mapped_device
!= dev
)) {
1057 if (unlikely(ssb_pci_switch_core(bus
, dev
)))
1060 iowrite16(value
, bus
->mmio
+ offset
);
1063 static void ssb_pci_write32(struct ssb_device
*dev
, u16 offset
, u32 value
)
1065 struct ssb_bus
*bus
= dev
->bus
;
1067 if (unlikely(ssb_pci_assert_buspower(bus
)))
1069 if (unlikely(bus
->mapped_device
!= dev
)) {
1070 if (unlikely(ssb_pci_switch_core(bus
, dev
)))
1073 iowrite32(value
, bus
->mmio
+ offset
);
1076 #ifdef CONFIG_SSB_BLOCKIO
1077 static void ssb_pci_block_write(struct ssb_device
*dev
, const void *buffer
,
1078 size_t count
, u16 offset
, u8 reg_width
)
1080 struct ssb_bus
*bus
= dev
->bus
;
1081 void __iomem
*addr
= bus
->mmio
+ offset
;
1083 if (unlikely(ssb_pci_assert_buspower(bus
)))
1085 if (unlikely(bus
->mapped_device
!= dev
)) {
1086 if (unlikely(ssb_pci_switch_core(bus
, dev
)))
1089 switch (reg_width
) {
1091 iowrite8_rep(addr
, buffer
, count
);
1095 iowrite16_rep(addr
, buffer
, count
>> 1);
1099 iowrite32_rep(addr
, buffer
, count
>> 2);
1105 #endif /* CONFIG_SSB_BLOCKIO */
1107 /* Not "static", as it's used in main.c */
1108 const struct ssb_bus_ops ssb_pci_ops
= {
1109 .read8
= ssb_pci_read8
,
1110 .read16
= ssb_pci_read16
,
1111 .read32
= ssb_pci_read32
,
1112 .write8
= ssb_pci_write8
,
1113 .write16
= ssb_pci_write16
,
1114 .write32
= ssb_pci_write32
,
1115 #ifdef CONFIG_SSB_BLOCKIO
1116 .block_read
= ssb_pci_block_read
,
1117 .block_write
= ssb_pci_block_write
,
1121 static ssize_t
ssb_pci_attr_sprom_show(struct device
*pcidev
,
1122 struct device_attribute
*attr
,
1125 struct pci_dev
*pdev
= container_of(pcidev
, struct pci_dev
, dev
);
1126 struct ssb_bus
*bus
;
1128 bus
= ssb_pci_dev_to_bus(pdev
);
1132 return ssb_attr_sprom_show(bus
, buf
, sprom_do_read
);
1135 static ssize_t
ssb_pci_attr_sprom_store(struct device
*pcidev
,
1136 struct device_attribute
*attr
,
1137 const char *buf
, size_t count
)
1139 struct pci_dev
*pdev
= container_of(pcidev
, struct pci_dev
, dev
);
1140 struct ssb_bus
*bus
;
1142 bus
= ssb_pci_dev_to_bus(pdev
);
1146 return ssb_attr_sprom_store(bus
, buf
, count
,
1147 sprom_check_crc
, sprom_do_write
);
1150 static DEVICE_ATTR(ssb_sprom
, 0600,
1151 ssb_pci_attr_sprom_show
,
1152 ssb_pci_attr_sprom_store
);
1154 void ssb_pci_exit(struct ssb_bus
*bus
)
1156 struct pci_dev
*pdev
;
1158 if (bus
->bustype
!= SSB_BUSTYPE_PCI
)
1161 pdev
= bus
->host_pci
;
1162 device_remove_file(&pdev
->dev
, &dev_attr_ssb_sprom
);
1165 int ssb_pci_init(struct ssb_bus
*bus
)
1167 struct pci_dev
*pdev
;
1170 if (bus
->bustype
!= SSB_BUSTYPE_PCI
)
1173 pdev
= bus
->host_pci
;
1174 mutex_init(&bus
->sprom_mutex
);
1175 err
= device_create_file(&pdev
->dev
, &dev_attr_ssb_sprom
);