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 <linux/ssb/ssb.h>
19 #include <linux/ssb/ssb_regs.h>
20 #include <linux/slab.h>
21 #include <linux/pci.h>
22 #include <linux/delay.h>
24 #include "ssb_private.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 ssb_printk(KERN_ERR PFX "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 ssb_printk(KERN_INFO PFX
71 "Switching to %s core, index %d\n",
72 ssb_core_name(dev->id.coreid),
76 spin_lock_irqsave(&bus->bar_lock, flags);
77 err = ssb_pci_switch_coreidx(bus, dev->core_index);
79 bus->mapped_device = dev;
80 spin_unlock_irqrestore(&bus->bar_lock, flags);
85 /* Enable/disable the on board crystal oscillator and/or PLL. */
86 int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
89 u32 in, out, outenable;
92 if (bus->bustype != SSB_BUSTYPE_PCI)
95 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
98 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
101 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
108 /* Avoid glitching the clock if GPRS is already using it.
109 * We can't actually read the state of the PLLPD so we infer it
110 * by the value of XTAL_PU which *is* readable via gpioin.
112 if (!(in & SSB_GPIO_XTAL)) {
113 if (what & SSB_GPIO_XTAL) {
114 /* Turn the crystal on */
115 out |= SSB_GPIO_XTAL;
116 if (what & SSB_GPIO_PLL)
118 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
121 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
127 if (what & SSB_GPIO_PLL) {
128 /* Turn the PLL on */
129 out &= ~SSB_GPIO_PLL;
130 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
137 err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
140 pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
141 err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
145 if (what & SSB_GPIO_XTAL) {
146 /* Turn the crystal off */
147 out &= ~SSB_GPIO_XTAL;
149 if (what & SSB_GPIO_PLL) {
150 /* Turn the PLL off */
153 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
156 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
165 printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n");
170 /* Get the word-offset for a SSB_SPROM_XXX define. */
171 #define SPOFF(offset) ((offset) / sizeof(u16))
172 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
173 #define SPEX16(_outvar, _offset, _mask, _shift) \
174 out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
175 #define SPEX32(_outvar, _offset, _mask, _shift) \
176 out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
177 in[SPOFF(_offset)]) & (_mask)) >> (_shift))
178 #define SPEX(_outvar, _offset, _mask, _shift) \
179 SPEX16(_outvar, _offset, _mask, _shift)
181 #define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
183 SPEX(_field[0], _offset + 0, _mask, _shift); \
184 SPEX(_field[1], _offset + 2, _mask, _shift); \
185 SPEX(_field[2], _offset + 4, _mask, _shift); \
186 SPEX(_field[3], _offset + 6, _mask, _shift); \
187 SPEX(_field[4], _offset + 8, _mask, _shift); \
188 SPEX(_field[5], _offset + 10, _mask, _shift); \
189 SPEX(_field[6], _offset + 12, _mask, _shift); \
190 SPEX(_field[7], _offset + 14, _mask, _shift); \
194 static inline u8 ssb_crc8(u8 crc, u8 data)
196 /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
197 static const u8 t[] = {
198 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
199 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
200 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
201 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
202 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
203 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
204 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
205 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
206 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
207 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
208 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
209 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
210 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
211 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
212 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
213 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
214 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
215 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
216 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
217 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
218 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
219 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
220 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
221 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
222 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
223 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
224 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
225 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
226 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
227 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
228 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
229 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
231 return t[crc ^ data];
234 static void sprom_get_mac(char *mac, const u16 *in)
237 for (i = 0; i < 3; i++) {
243 static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
248 for (word = 0; word < size - 1; word++) {
249 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
250 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
252 crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
258 static int sprom_check_crc(const u16 *sprom, size_t size)
264 crc = ssb_sprom_crc(sprom, size);
265 tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
266 expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
267 if (crc != expected_crc)
273 static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
277 for (i = 0; i < bus->sprom_size; i++)
278 sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
283 static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
285 struct pci_dev *pdev = bus->host_pci;
288 u16 size = bus->sprom_size;
290 ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
291 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
294 spromctl |= SSB_SPROMCTL_WE;
295 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
298 ssb_printk(KERN_NOTICE PFX "[ 0%%");
300 for (i = 0; i < size; i++) {
303 else if (i == size / 2)
305 else if (i == (size * 3) / 4)
309 writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
313 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
316 spromctl &= ~SSB_SPROMCTL_WE;
317 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
321 ssb_printk("100%% ]\n");
322 ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
326 ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
330 static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
336 v = in[SPOFF(SSB_SPROM1_AGAIN)];
337 gain = (v & mask) >> shift;
339 gain = 2; /* If unset use 2dBm */
340 if (sprom_revision == 1) {
341 /* Convert to Q5.2 */
344 /* Q5.2 Fractional part is stored in 0xC0 */
345 gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
351 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
355 if (out->revision == 3) /* rev 3 moved MAC */
356 loc[0] = SSB_SPROM3_IL0MAC;
358 loc[0] = SSB_SPROM1_IL0MAC;
359 loc[1] = SSB_SPROM1_ET0MAC;
360 loc[2] = SSB_SPROM1_ET1MAC;
362 sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
363 if (out->revision < 3) { /* only rev 1-2 have et0, et1 */
364 sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
365 sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
367 SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
368 SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
369 SSB_SPROM1_ETHPHY_ET1A_SHIFT);
370 SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
371 SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
372 SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
373 if (out->revision == 1)
374 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
375 SSB_SPROM1_BINF_CCODE_SHIFT);
376 SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
377 SSB_SPROM1_BINF_ANTA_SHIFT);
378 SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
379 SSB_SPROM1_BINF_ANTBG_SHIFT);
380 SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
381 SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
382 SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
383 SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
384 SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
385 SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
386 SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
387 SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
388 SSB_SPROM1_GPIOA_P1_SHIFT);
389 SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
390 SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
391 SSB_SPROM1_GPIOB_P3_SHIFT);
392 SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
393 SSB_SPROM1_MAXPWR_A_SHIFT);
394 SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
395 SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
396 SSB_SPROM1_ITSSI_A_SHIFT);
397 SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
398 SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
399 if (out->revision >= 2)
400 SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
401 SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
402 SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
404 /* Extract the antenna gain values. */
405 out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
407 SSB_SPROM1_AGAIN_BG_SHIFT);
408 out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
410 SSB_SPROM1_AGAIN_A_SHIFT);
413 /* Revs 4 5 and 8 have partially shared layout */
414 static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
416 SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
417 SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
418 SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
419 SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
420 SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
421 SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
422 SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
423 SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
425 SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
426 SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
427 SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
428 SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
429 SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
430 SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
431 SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
432 SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
434 SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
435 SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
436 SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
437 SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
438 SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
439 SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
440 SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
441 SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
443 SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
444 SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
445 SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
446 SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
447 SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
448 SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
449 SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
450 SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
453 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
457 if (out->revision == 4)
458 il0mac_offset = SSB_SPROM4_IL0MAC;
460 il0mac_offset = SSB_SPROM5_IL0MAC;
462 sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
464 SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
465 SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
466 SSB_SPROM4_ETHPHY_ET1A_SHIFT);
467 SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
468 if (out->revision == 4) {
469 SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
470 SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
471 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
472 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
473 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
474 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
476 SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
477 SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
478 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
479 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
480 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
481 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
483 SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
484 SSB_SPROM4_ANTAVAIL_A_SHIFT);
485 SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
486 SSB_SPROM4_ANTAVAIL_BG_SHIFT);
487 SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
488 SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
489 SSB_SPROM4_ITSSI_BG_SHIFT);
490 SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
491 SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
492 SSB_SPROM4_ITSSI_A_SHIFT);
493 if (out->revision == 4) {
494 SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
495 SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
496 SSB_SPROM4_GPIOA_P1_SHIFT);
497 SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
498 SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
499 SSB_SPROM4_GPIOB_P3_SHIFT);
501 SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
502 SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
503 SSB_SPROM5_GPIOA_P1_SHIFT);
504 SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
505 SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
506 SSB_SPROM5_GPIOB_P3_SHIFT);
509 /* Extract the antenna gain values. */
510 SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
511 SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
512 SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
513 SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
514 SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
515 SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
516 SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
517 SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
519 sprom_extract_r458(out, in);
521 /* TODO - get remaining rev 4 stuff needed */
524 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
528 u16 pwr_info_offset[] = {
529 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
530 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
532 BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
533 ARRAY_SIZE(out->core_pwr_info));
535 /* extract the MAC address */
536 sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
538 SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
539 SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
540 SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
541 SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
542 SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
543 SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
544 SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
545 SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
546 SSB_SPROM8_ANTAVAIL_A_SHIFT);
547 SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
548 SSB_SPROM8_ANTAVAIL_BG_SHIFT);
549 SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
550 SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
551 SSB_SPROM8_ITSSI_BG_SHIFT);
552 SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
553 SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
554 SSB_SPROM8_ITSSI_A_SHIFT);
555 SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
556 SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
557 SSB_SPROM8_MAXP_AL_SHIFT);
558 SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
559 SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
560 SSB_SPROM8_GPIOA_P1_SHIFT);
561 SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
562 SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
563 SSB_SPROM8_GPIOB_P3_SHIFT);
564 SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
565 SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
566 SSB_SPROM8_TRI5G_SHIFT);
567 SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
568 SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
569 SSB_SPROM8_TRI5GH_SHIFT);
570 SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
571 SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
572 SSB_SPROM8_RXPO5G_SHIFT);
573 SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
574 SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
575 SSB_SPROM8_RSSISMC2G_SHIFT);
576 SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
577 SSB_SPROM8_RSSISAV2G_SHIFT);
578 SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
579 SSB_SPROM8_BXA2G_SHIFT);
580 SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
581 SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
582 SSB_SPROM8_RSSISMC5G_SHIFT);
583 SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
584 SSB_SPROM8_RSSISAV5G_SHIFT);
585 SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
586 SSB_SPROM8_BXA5G_SHIFT);
587 SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
588 SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
589 SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
590 SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
591 SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
592 SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
593 SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
594 SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
595 SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
596 SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
597 SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
598 SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
599 SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
600 SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
601 SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
602 SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
603 SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
605 /* Extract the antenna gain values. */
606 SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
607 SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
608 SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
609 SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
610 SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
611 SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
612 SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
613 SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
615 /* Extract cores power info info */
616 for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
617 o = pwr_info_offset[i];
618 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
619 SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
620 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
621 SSB_SPROM8_2G_MAXP, 0);
623 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
624 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
625 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
627 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
628 SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
629 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
630 SSB_SPROM8_5G_MAXP, 0);
631 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
632 SSB_SPROM8_5GH_MAXP, 0);
633 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
634 SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
636 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
637 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
638 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
639 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
640 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
641 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
642 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
643 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
644 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
647 /* Extract FEM info */
648 SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
649 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
650 SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
651 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
652 SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
653 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
654 SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
655 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
656 SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
657 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
659 SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
660 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
661 SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
662 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
663 SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
664 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
665 SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
666 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
667 SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
668 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
670 SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
671 SSB_SPROM8_LEDDC_ON_SHIFT);
672 SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
673 SSB_SPROM8_LEDDC_OFF_SHIFT);
675 SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
676 SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
677 SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
678 SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
679 SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
680 SSB_SPROM8_TXRXC_SWITCH_SHIFT);
682 SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
684 SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
685 SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
686 SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
687 SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
689 SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
690 SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
691 SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
692 SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
693 SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
694 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
695 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
696 SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
697 SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
698 SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
699 SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
700 SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
701 SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
702 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
703 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
704 SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
705 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
706 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
707 SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
708 SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
710 SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
711 SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
712 SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
713 SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
715 SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
716 SSB_SPROM8_THERMAL_TRESH_SHIFT);
717 SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
718 SSB_SPROM8_THERMAL_OFFSET_SHIFT);
719 SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
720 SSB_SPROM8_TEMPDELTA_PHYCAL,
721 SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
722 SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
723 SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
724 SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
725 SSB_SPROM8_TEMPDELTA_HYSTERESIS,
726 SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
727 sprom_extract_r458(out, in);
729 /* TODO - get remaining rev 8 stuff needed */
732 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
733 const u16 *in, u16 size)
735 memset(out, 0, sizeof(*out));
737 out->revision = in[size - 1] & 0x00FF;
738 ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
739 memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
740 memset(out->et1mac, 0xFF, 6);
742 if ((bus->chip_id & 0xFF00) == 0x4400) {
743 /* Workaround: The BCM44XX chip has a stupid revision
744 * number stored in the SPROM.
745 * Always extract r1. */
747 ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
750 switch (out->revision) {
754 sprom_extract_r123(out, in);
758 sprom_extract_r45(out, in);
761 sprom_extract_r8(out, in);
764 ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
765 " revision %d detected. Will extract"
766 " v1\n", out->revision);
768 sprom_extract_r123(out, in);
771 if (out->boardflags_lo == 0xFFFF)
772 out->boardflags_lo = 0; /* per specs */
773 if (out->boardflags_hi == 0xFFFF)
774 out->boardflags_hi = 0; /* per specs */
779 static int ssb_pci_sprom_get(struct ssb_bus *bus,
780 struct ssb_sprom *sprom)
785 if (!ssb_is_sprom_available(bus)) {
786 ssb_printk(KERN_ERR PFX "No SPROM available!\n");
789 if (bus->chipco.dev) { /* can be unavailable! */
791 * get SPROM offset: SSB_SPROM_BASE1 except for
792 * chipcommon rev >= 31 or chip ID is 0x4312 and
793 * chipcommon status & 3 == 2
795 if (bus->chipco.dev->id.revision >= 31)
796 bus->sprom_offset = SSB_SPROM_BASE31;
797 else if (bus->chip_id == 0x4312 &&
798 (bus->chipco.status & 0x03) == 2)
799 bus->sprom_offset = SSB_SPROM_BASE31;
801 bus->sprom_offset = SSB_SPROM_BASE1;
803 bus->sprom_offset = SSB_SPROM_BASE1;
805 ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
807 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
810 bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
811 sprom_do_read(bus, buf);
812 err = sprom_check_crc(buf, bus->sprom_size);
814 /* try for a 440 byte SPROM - revision 4 and higher */
816 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
820 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
821 sprom_do_read(bus, buf);
822 err = sprom_check_crc(buf, bus->sprom_size);
824 /* All CRC attempts failed.
825 * Maybe there is no SPROM on the device?
826 * Now we ask the arch code if there is some sprom
827 * available for this device in some other storage */
828 err = ssb_fill_sprom_with_fallback(bus, sprom);
830 ssb_printk(KERN_WARNING PFX "WARNING: Using"
831 " fallback SPROM failed (err %d)\n",
834 ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
835 " revision %d provided by"
836 " platform.\n", sprom->revision);
840 ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
841 " SPROM CRC (corrupt SPROM)\n");
844 err = sprom_extract(bus, sprom, buf, bus->sprom_size);
851 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
852 struct ssb_boardinfo *bi)
854 bi->vendor = bus->host_pci->subsystem_vendor;
855 bi->type = bus->host_pci->subsystem_device;
858 int ssb_pci_get_invariants(struct ssb_bus *bus,
859 struct ssb_init_invariants *iv)
863 err = ssb_pci_sprom_get(bus, &iv->sprom);
866 ssb_pci_get_boardinfo(bus, &iv->boardinfo);
872 #ifdef CONFIG_SSB_DEBUG
873 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
875 if (likely(bus->powered_up))
878 printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
879 "while accessing PCI MMIO space\n");
880 if (bus->power_warn_count <= 10) {
881 bus->power_warn_count++;
888 static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
894 static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
896 struct ssb_bus *bus = dev->bus;
898 if (unlikely(ssb_pci_assert_buspower(bus)))
900 if (unlikely(bus->mapped_device != dev)) {
901 if (unlikely(ssb_pci_switch_core(bus, dev)))
904 return ioread8(bus->mmio + offset);
907 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
909 struct ssb_bus *bus = dev->bus;
911 if (unlikely(ssb_pci_assert_buspower(bus)))
913 if (unlikely(bus->mapped_device != dev)) {
914 if (unlikely(ssb_pci_switch_core(bus, dev)))
917 return ioread16(bus->mmio + offset);
920 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
922 struct ssb_bus *bus = dev->bus;
924 if (unlikely(ssb_pci_assert_buspower(bus)))
926 if (unlikely(bus->mapped_device != dev)) {
927 if (unlikely(ssb_pci_switch_core(bus, dev)))
930 return ioread32(bus->mmio + offset);
933 #ifdef CONFIG_SSB_BLOCKIO
934 static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
935 size_t count, u16 offset, u8 reg_width)
937 struct ssb_bus *bus = dev->bus;
938 void __iomem *addr = bus->mmio + offset;
940 if (unlikely(ssb_pci_assert_buspower(bus)))
942 if (unlikely(bus->mapped_device != dev)) {
943 if (unlikely(ssb_pci_switch_core(bus, dev)))
948 ioread8_rep(addr, buffer, count);
951 SSB_WARN_ON(count & 1);
952 ioread16_rep(addr, buffer, count >> 1);
955 SSB_WARN_ON(count & 3);
956 ioread32_rep(addr, buffer, count >> 2);
964 memset(buffer, 0xFF, count);
966 #endif /* CONFIG_SSB_BLOCKIO */
968 static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
970 struct ssb_bus *bus = dev->bus;
972 if (unlikely(ssb_pci_assert_buspower(bus)))
974 if (unlikely(bus->mapped_device != dev)) {
975 if (unlikely(ssb_pci_switch_core(bus, dev)))
978 iowrite8(value, bus->mmio + offset);
981 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
983 struct ssb_bus *bus = dev->bus;
985 if (unlikely(ssb_pci_assert_buspower(bus)))
987 if (unlikely(bus->mapped_device != dev)) {
988 if (unlikely(ssb_pci_switch_core(bus, dev)))
991 iowrite16(value, bus->mmio + offset);
994 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
996 struct ssb_bus *bus = dev->bus;
998 if (unlikely(ssb_pci_assert_buspower(bus)))
1000 if (unlikely(bus->mapped_device != dev)) {
1001 if (unlikely(ssb_pci_switch_core(bus, dev)))
1004 iowrite32(value, bus->mmio + offset);
1007 #ifdef CONFIG_SSB_BLOCKIO
1008 static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1009 size_t count, u16 offset, u8 reg_width)
1011 struct ssb_bus *bus = dev->bus;
1012 void __iomem *addr = bus->mmio + offset;
1014 if (unlikely(ssb_pci_assert_buspower(bus)))
1016 if (unlikely(bus->mapped_device != dev)) {
1017 if (unlikely(ssb_pci_switch_core(bus, dev)))
1020 switch (reg_width) {
1022 iowrite8_rep(addr, buffer, count);
1025 SSB_WARN_ON(count & 1);
1026 iowrite16_rep(addr, buffer, count >> 1);
1029 SSB_WARN_ON(count & 3);
1030 iowrite32_rep(addr, buffer, count >> 2);
1036 #endif /* CONFIG_SSB_BLOCKIO */
1038 /* Not "static", as it's used in main.c */
1039 const struct ssb_bus_ops ssb_pci_ops = {
1040 .read8 = ssb_pci_read8,
1041 .read16 = ssb_pci_read16,
1042 .read32 = ssb_pci_read32,
1043 .write8 = ssb_pci_write8,
1044 .write16 = ssb_pci_write16,
1045 .write32 = ssb_pci_write32,
1046 #ifdef CONFIG_SSB_BLOCKIO
1047 .block_read = ssb_pci_block_read,
1048 .block_write = ssb_pci_block_write,
1052 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1053 struct device_attribute *attr,
1056 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1057 struct ssb_bus *bus;
1059 bus = ssb_pci_dev_to_bus(pdev);
1063 return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1066 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1067 struct device_attribute *attr,
1068 const char *buf, size_t count)
1070 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1071 struct ssb_bus *bus;
1073 bus = ssb_pci_dev_to_bus(pdev);
1077 return ssb_attr_sprom_store(bus, buf, count,
1078 sprom_check_crc, sprom_do_write);
1081 static DEVICE_ATTR(ssb_sprom, 0600,
1082 ssb_pci_attr_sprom_show,
1083 ssb_pci_attr_sprom_store);
1085 void ssb_pci_exit(struct ssb_bus *bus)
1087 struct pci_dev *pdev;
1089 if (bus->bustype != SSB_BUSTYPE_PCI)
1092 pdev = bus->host_pci;
1093 device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1096 int ssb_pci_init(struct ssb_bus *bus)
1098 struct pci_dev *pdev;
1101 if (bus->bustype != SSB_BUSTYPE_PCI)
1104 pdev = bus->host_pci;
1105 mutex_init(&bus->sprom_mutex);
1106 err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);