2 * Sonics Silicon Backplane PCI-Hostbus related functions.
4 * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de>
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/pci.h>
21 #include <linux/delay.h>
23 #include "ssb_private.h"
26 /* Define the following to 1 to enable a printk on each coreswitch. */
27 #define SSB_VERBOSE_PCICORESWITCH_DEBUG 0
30 /* Lowlevel coreswitching */
31 int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
38 err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
39 (coreidx * SSB_CORE_SIZE)
43 err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
47 cur_core = (cur_core - SSB_ENUM_BASE)
49 if (cur_core == coreidx)
52 if (attempts++ > SSB_BAR0_MAX_RETRIES)
58 ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
62 int ssb_pci_switch_core(struct ssb_bus *bus,
63 struct ssb_device *dev)
68 #if SSB_VERBOSE_PCICORESWITCH_DEBUG
69 ssb_printk(KERN_INFO PFX
70 "Switching to %s core, index %d\n",
71 ssb_core_name(dev->id.coreid),
75 spin_lock_irqsave(&bus->bar_lock, flags);
76 err = ssb_pci_switch_coreidx(bus, dev->core_index);
78 bus->mapped_device = dev;
79 spin_unlock_irqrestore(&bus->bar_lock, flags);
84 /* Enable/disable the on board crystal oscillator and/or PLL. */
85 int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
88 u32 in, out, outenable;
91 if (bus->bustype != SSB_BUSTYPE_PCI)
94 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
97 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
100 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
107 /* Avoid glitching the clock if GPRS is already using it.
108 * We can't actually read the state of the PLLPD so we infer it
109 * by the value of XTAL_PU which *is* readable via gpioin.
111 if (!(in & SSB_GPIO_XTAL)) {
112 if (what & SSB_GPIO_XTAL) {
113 /* Turn the crystal on */
114 out |= SSB_GPIO_XTAL;
115 if (what & SSB_GPIO_PLL)
117 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
120 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
126 if (what & SSB_GPIO_PLL) {
127 /* Turn the PLL on */
128 out &= ~SSB_GPIO_PLL;
129 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
136 err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
139 pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
140 err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
144 if (what & SSB_GPIO_XTAL) {
145 /* Turn the crystal off */
146 out &= ~SSB_GPIO_XTAL;
148 if (what & SSB_GPIO_PLL) {
149 /* Turn the PLL off */
152 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
155 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
164 printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n");
169 /* Get the word-offset for a SSB_SPROM_XXX define. */
170 #define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16))
171 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
172 #define SPEX(_outvar, _offset, _mask, _shift) \
173 out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
175 static inline u8 ssb_crc8(u8 crc, u8 data)
177 /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
178 static const u8 t[] = {
179 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
180 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
181 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
182 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
183 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
184 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
185 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
186 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
187 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
188 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
189 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
190 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
191 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
192 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
193 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
194 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
195 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
196 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
197 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
198 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
199 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
200 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
201 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
202 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
203 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
204 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
205 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
206 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
207 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
208 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
209 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
210 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
212 return t[crc ^ data];
215 static u8 ssb_sprom_crc(const u16 *sprom)
220 for (word = 0; word < SSB_SPROMSIZE_WORDS - 1; word++) {
221 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
222 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
224 crc = ssb_crc8(crc, sprom[SPOFF(SSB_SPROM_REVISION)] & 0x00FF);
230 static int sprom_check_crc(const u16 *sprom)
236 crc = ssb_sprom_crc(sprom);
237 tmp = sprom[SPOFF(SSB_SPROM_REVISION)] & SSB_SPROM_REVISION_CRC;
238 expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
239 if (crc != expected_crc)
245 static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
249 for (i = 0; i < SSB_SPROMSIZE_WORDS; i++)
250 sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2));
253 static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
255 struct pci_dev *pdev = bus->host_pci;
259 ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
260 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
263 spromctl |= SSB_SPROMCTL_WE;
264 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
267 ssb_printk(KERN_NOTICE PFX "[ 0%%");
269 for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
270 if (i == SSB_SPROMSIZE_WORDS / 4)
272 else if (i == SSB_SPROMSIZE_WORDS / 2)
274 else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3)
278 writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
282 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
285 spromctl &= ~SSB_SPROMCTL_WE;
286 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
290 ssb_printk("100%% ]\n");
291 ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
295 ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
299 static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)
304 SPEX(pci_spid, SSB_SPROM1_SPID, 0xFFFF, 0);
305 SPEX(pci_svid, SSB_SPROM1_SVID, 0xFFFF, 0);
306 SPEX(pci_pid, SSB_SPROM1_PID, 0xFFFF, 0);
307 for (i = 0; i < 3; i++) {
308 v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
309 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
311 for (i = 0; i < 3; i++) {
312 v = in[SPOFF(SSB_SPROM1_ET0MAC) + i];
313 *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
315 for (i = 0; i < 3; i++) {
316 v = in[SPOFF(SSB_SPROM1_ET1MAC) + i];
317 *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
319 SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
320 SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
321 SSB_SPROM1_ETHPHY_ET1A_SHIFT);
322 SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
323 SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
324 SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
325 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
326 SSB_SPROM1_BINF_CCODE_SHIFT);
327 SPEX(antenna_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
328 SSB_SPROM1_BINF_ANTA_SHIFT);
329 SPEX(antenna_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
330 SSB_SPROM1_BINF_ANTBG_SHIFT);
331 SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
332 SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
333 SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
334 SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
335 SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
336 SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
337 SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
338 SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
339 SSB_SPROM1_GPIOA_P1_SHIFT);
340 SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
341 SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
342 SSB_SPROM1_GPIOB_P3_SHIFT);
343 SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
344 SSB_SPROM1_MAXPWR_A_SHIFT);
345 SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
346 SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
347 SSB_SPROM1_ITSSI_A_SHIFT);
348 SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
349 SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
350 SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0);
351 SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG,
352 SSB_SPROM1_AGAIN_BG_SHIFT);
353 for (i = 0; i < 4; i++) {
354 v = in[SPOFF(SSB_SPROM1_OEM) + i];
355 *(((__le16 *)out->oem) + i) = cpu_to_le16(v);
359 static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in)
364 SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
365 SPEX(maxpwr_a_hi, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
366 SPEX(maxpwr_a_lo, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
367 SSB_SPROM2_MAXP_A_LO_SHIFT);
368 SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
369 SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
370 SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
371 SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
372 SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
373 SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
374 SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
375 for (i = 0; i < 4; i++) {
376 v = in[SPOFF(SSB_SPROM2_CCODE) + i];
377 *(((__le16 *)out->country_str) + i) = cpu_to_le16(v);
381 static void sprom_extract_r3(struct ssb_sprom_r3 *out, const u16 *in)
383 out->ofdmapo = (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0xFF00) >> 8;
384 out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0x00FF) << 8;
386 out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0xFF00) >> 8;
387 out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0x00FF) << 8;
389 out->ofdmalpo = (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0xFF00) >> 8;
390 out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0x00FF) << 8;
391 out->ofdmalpo <<= 16;
392 out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0xFF00) >> 8;
393 out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0x00FF) << 8;
395 out->ofdmahpo = (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0xFF00) >> 8;
396 out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0x00FF) << 8;
397 out->ofdmahpo <<= 16;
398 out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0xFF00) >> 8;
399 out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0x00FF) << 8;
401 SPEX(gpioldc_on_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_ON,
402 SSB_SPROM3_GPIOLDC_ON_SHIFT);
403 SPEX(gpioldc_off_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_OFF,
404 SSB_SPROM3_GPIOLDC_OFF_SHIFT);
405 SPEX(cckpo_1M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_1M, 0);
406 SPEX(cckpo_2M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_2M,
407 SSB_SPROM3_CCKPO_2M_SHIFT);
408 SPEX(cckpo_55M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_55M,
409 SSB_SPROM3_CCKPO_55M_SHIFT);
410 SPEX(cckpo_11M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_11M,
411 SSB_SPROM3_CCKPO_11M_SHIFT);
413 out->ofdmgpo = (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0xFF00) >> 8;
414 out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0x00FF) << 8;
416 out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0xFF00) >> 8;
417 out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0x00FF) << 8;
420 static int sprom_extract(struct ssb_bus *bus,
421 struct ssb_sprom *out, const u16 *in)
423 memset(out, 0, sizeof(*out));
425 SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0);
427 if ((bus->chip_id & 0xFF00) == 0x4400) {
428 /* Workaround: The BCM44XX chip has a stupid revision
429 * number stored in the SPROM.
430 * Always extract r1. */
431 sprom_extract_r1(&out->r1, in);
433 if (out->revision == 0)
435 if (out->revision >= 1 && out->revision <= 3)
436 sprom_extract_r1(&out->r1, in);
437 if (out->revision >= 2 && out->revision <= 3)
438 sprom_extract_r2(&out->r2, in);
439 if (out->revision == 3)
440 sprom_extract_r3(&out->r3, in);
441 if (out->revision >= 4)
447 ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
448 "detected. Will extract v1\n", out->revision);
449 sprom_extract_r1(&out->r1, in);
453 static int ssb_pci_sprom_get(struct ssb_bus *bus,
454 struct ssb_sprom *sprom)
459 buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
462 sprom_do_read(bus, buf);
463 err = sprom_check_crc(buf);
465 ssb_printk(KERN_WARNING PFX
466 "WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
468 err = sprom_extract(bus, sprom, buf);
475 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
476 struct ssb_boardinfo *bi)
478 pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
480 pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
482 pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
486 int ssb_pci_get_invariants(struct ssb_bus *bus,
487 struct ssb_init_invariants *iv)
491 err = ssb_pci_sprom_get(bus, &iv->sprom);
494 ssb_pci_get_boardinfo(bus, &iv->boardinfo);
500 #ifdef CONFIG_SSB_DEBUG
501 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
503 if (likely(bus->powered_up))
506 printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
507 "while accessing PCI MMIO space\n");
508 if (bus->power_warn_count <= 10) {
509 bus->power_warn_count++;
516 static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
522 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
524 struct ssb_bus *bus = dev->bus;
526 if (unlikely(ssb_pci_assert_buspower(bus)))
528 if (unlikely(bus->mapped_device != dev)) {
529 if (unlikely(ssb_pci_switch_core(bus, dev)))
532 return ioread16(bus->mmio + offset);
535 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
537 struct ssb_bus *bus = dev->bus;
539 if (unlikely(ssb_pci_assert_buspower(bus)))
541 if (unlikely(bus->mapped_device != dev)) {
542 if (unlikely(ssb_pci_switch_core(bus, dev)))
545 return ioread32(bus->mmio + offset);
548 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
550 struct ssb_bus *bus = dev->bus;
552 if (unlikely(ssb_pci_assert_buspower(bus)))
554 if (unlikely(bus->mapped_device != dev)) {
555 if (unlikely(ssb_pci_switch_core(bus, dev)))
558 iowrite16(value, bus->mmio + offset);
561 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
563 struct ssb_bus *bus = dev->bus;
565 if (unlikely(ssb_pci_assert_buspower(bus)))
567 if (unlikely(bus->mapped_device != dev)) {
568 if (unlikely(ssb_pci_switch_core(bus, dev)))
571 iowrite32(value, bus->mmio + offset);
574 /* Not "static", as it's used in main.c */
575 const struct ssb_bus_ops ssb_pci_ops = {
576 .read16 = ssb_pci_read16,
577 .read32 = ssb_pci_read32,
578 .write16 = ssb_pci_write16,
579 .write32 = ssb_pci_write32,
582 static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
586 for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
587 pos += snprintf(buf + pos, buf_len - pos - 1,
588 "%04X", swab16(sprom[i]) & 0xFFFF);
590 pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
595 static int hex2sprom(u16 *sprom, const char *dump, size_t len)
599 unsigned long parsed;
601 if (len < SSB_SPROMSIZE_BYTES * 2)
604 while (cnt < SSB_SPROMSIZE_WORDS) {
605 memcpy(tmp, dump, 4);
607 parsed = simple_strtoul(tmp, NULL, 16);
608 sprom[cnt++] = swab16((u16)parsed);
614 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
615 struct device_attribute *attr,
618 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
624 bus = ssb_pci_dev_to_bus(pdev);
628 sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
632 /* Use interruptible locking, as the SPROM write might
633 * be holding the lock for several seconds. So allow userspace
634 * to cancel operation. */
636 if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
638 sprom_do_read(bus, sprom);
639 mutex_unlock(&bus->pci_sprom_mutex);
641 count = sprom2hex(sprom, buf, PAGE_SIZE);
647 return err ? err : count;
650 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
651 struct device_attribute *attr,
652 const char *buf, size_t count)
654 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
657 int res = 0, err = -ENODEV;
659 bus = ssb_pci_dev_to_bus(pdev);
663 sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
666 err = hex2sprom(sprom, buf, count);
671 err = sprom_check_crc(sprom);
677 /* Use interruptible locking, as the SPROM write might
678 * be holding the lock for several seconds. So allow userspace
679 * to cancel operation. */
681 if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
683 err = ssb_devices_freeze(bus);
684 if (err == -EOPNOTSUPP) {
685 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
686 "No suspend support. Is CONFIG_PM enabled?\n");
690 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
693 res = sprom_do_write(bus, sprom);
694 err = ssb_devices_thaw(bus);
696 ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
698 mutex_unlock(&bus->pci_sprom_mutex);
704 return err ? err : count;
707 static DEVICE_ATTR(ssb_sprom, 0600,
708 ssb_pci_attr_sprom_show,
709 ssb_pci_attr_sprom_store);
711 void ssb_pci_exit(struct ssb_bus *bus)
713 struct pci_dev *pdev;
715 if (bus->bustype != SSB_BUSTYPE_PCI)
718 pdev = bus->host_pci;
719 device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
722 int ssb_pci_init(struct ssb_bus *bus)
724 struct pci_dev *pdev;
727 if (bus->bustype != SSB_BUSTYPE_PCI)
730 pdev = bus->host_pci;
731 mutex_init(&bus->pci_sprom_mutex);
732 err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);