rtc: pcf8523: don't return invalid date when battery is low
[linux-2.6-block.git] / drivers / ssb / pci.c
CommitLineData
61e115a5
MB
1/*
2 * Sonics Silicon Backplane PCI-Hostbus related functions.
3 *
eb032b98 4 * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
61e115a5
MB
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>
9 *
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.
14 *
15 * Licensed under the GNU/GPL. See COPYING for details.
16 */
17
b8b6069c
MB
18#include "ssb_private.h"
19
61e115a5
MB
20#include <linux/ssb/ssb.h>
21#include <linux/ssb/ssb_regs.h>
5a0e3ad6 22#include <linux/slab.h>
61e115a5
MB
23#include <linux/pci.h>
24#include <linux/delay.h>
25
61e115a5
MB
26
27/* Define the following to 1 to enable a printk on each coreswitch. */
28#define SSB_VERBOSE_PCICORESWITCH_DEBUG 0
29
30
31/* Lowlevel coreswitching */
32int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
33{
34 int err;
35 int attempts = 0;
36 u32 cur_core;
37
38 while (1) {
39 err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
40 (coreidx * SSB_CORE_SIZE)
41 + SSB_ENUM_BASE);
42 if (err)
43 goto error;
44 err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
45 &cur_core);
46 if (err)
47 goto error;
48 cur_core = (cur_core - SSB_ENUM_BASE)
49 / SSB_CORE_SIZE;
50 if (cur_core == coreidx)
51 break;
52
53 if (attempts++ > SSB_BAR0_MAX_RETRIES)
54 goto error;
55 udelay(10);
56 }
57 return 0;
58error:
b8b6069c 59 pr_err("Failed to switch to core %u\n", coreidx);
61e115a5
MB
60 return -ENODEV;
61}
62
63int ssb_pci_switch_core(struct ssb_bus *bus,
64 struct ssb_device *dev)
65{
66 int err;
67 unsigned long flags;
68
69#if SSB_VERBOSE_PCICORESWITCH_DEBUG
b8b6069c
MB
70 pr_info("Switching to %s core, index %d\n",
71 ssb_core_name(dev->id.coreid), dev->core_index);
61e115a5
MB
72#endif
73
74 spin_lock_irqsave(&bus->bar_lock, flags);
75 err = ssb_pci_switch_coreidx(bus, dev->core_index);
76 if (!err)
77 bus->mapped_device = dev;
78 spin_unlock_irqrestore(&bus->bar_lock, flags);
79
80 return err;
81}
82
83/* Enable/disable the on board crystal oscillator and/or PLL. */
84int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
85{
86 int err;
87 u32 in, out, outenable;
88 u16 pci_status;
89
90 if (bus->bustype != SSB_BUSTYPE_PCI)
91 return 0;
92
93 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
94 if (err)
95 goto err_pci;
96 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
97 if (err)
98 goto err_pci;
99 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
100 if (err)
101 goto err_pci;
102
103 outenable |= what;
104
105 if (turn_on) {
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.
109 */
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)
115 out |= SSB_GPIO_PLL;
116 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
117 if (err)
118 goto err_pci;
119 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
120 outenable);
121 if (err)
122 goto err_pci;
123 msleep(1);
124 }
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);
129 if (err)
130 goto err_pci;
131 msleep(5);
132 }
133 }
134
135 err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
136 if (err)
137 goto err_pci;
138 pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
139 err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
140 if (err)
141 goto err_pci;
142 } else {
143 if (what & SSB_GPIO_XTAL) {
144 /* Turn the crystal off */
145 out &= ~SSB_GPIO_XTAL;
146 }
147 if (what & SSB_GPIO_PLL) {
148 /* Turn the PLL off */
149 out |= SSB_GPIO_PLL;
150 }
151 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
152 if (err)
153 goto err_pci;
154 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
155 if (err)
156 goto err_pci;
157 }
158
159out:
160 return err;
161
162err_pci:
b8b6069c 163 pr_err("Error: ssb_pci_xtal() could not access PCI config space!\n");
61e115a5
MB
164 err = -EBUSY;
165 goto out;
166}
167
168/* Get the word-offset for a SSB_SPROM_XXX define. */
0a182fd8 169#define SPOFF(offset) ((offset) / sizeof(u16))
61e115a5 170/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
f679056b 171#define SPEX16(_outvar, _offset, _mask, _shift) \
61e115a5 172 out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
f679056b
GS
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)
178
e2da4bd3
HM
179#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
180 do { \
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); \
189 } while (0)
190
61e115a5
MB
191
192static inline u8 ssb_crc8(u8 crc, u8 data)
193{
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,
228 };
229 return t[crc ^ data];
230}
231
e5652756
JP
232static void sprom_get_mac(char *mac, const u16 *in)
233{
234 int i;
235 for (i = 0; i < 3; i++) {
e5652756 236 *mac++ = in[i] >> 8;
a9fac739 237 *mac++ = in[i];
e5652756
JP
238 }
239}
240
c272ef44 241static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
61e115a5
MB
242{
243 int word;
244 u8 crc = 0xFF;
245
c272ef44 246 for (word = 0; word < size - 1; word++) {
61e115a5
MB
247 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
248 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
249 }
c272ef44 250 crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
61e115a5
MB
251 crc ^= 0xFF;
252
253 return crc;
254}
255
e7ec2e32 256static int sprom_check_crc(const u16 *sprom, size_t size)
61e115a5
MB
257{
258 u8 crc;
259 u8 expected_crc;
260 u16 tmp;
261
c272ef44
LF
262 crc = ssb_sprom_crc(sprom, size);
263 tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
61e115a5
MB
264 expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
265 if (crc != expected_crc)
266 return -EPROTO;
267
268 return 0;
269}
270
e7ec2e32 271static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
61e115a5
MB
272{
273 int i;
274
c272ef44 275 for (i = 0; i < bus->sprom_size; i++)
ea2db495 276 sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
e7ec2e32
MB
277
278 return 0;
61e115a5
MB
279}
280
281static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
282{
283 struct pci_dev *pdev = bus->host_pci;
284 int i, err;
285 u32 spromctl;
c272ef44 286 u16 size = bus->sprom_size;
61e115a5 287
b8b6069c 288 pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
61e115a5
MB
289 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
290 if (err)
291 goto err_ctlreg;
292 spromctl |= SSB_SPROMCTL_WE;
293 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
294 if (err)
295 goto err_ctlreg;
b8b6069c 296 pr_notice("[ 0%%");
61e115a5 297 msleep(500);
c272ef44
LF
298 for (i = 0; i < size; i++) {
299 if (i == size / 4)
b8b6069c 300 pr_cont("25%%");
c272ef44 301 else if (i == size / 2)
b8b6069c 302 pr_cont("50%%");
c272ef44 303 else if (i == (size * 3) / 4)
b8b6069c 304 pr_cont("75%%");
61e115a5 305 else if (i % 2)
b8b6069c 306 pr_cont(".");
ea2db495 307 writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
61e115a5
MB
308 mmiowb();
309 msleep(20);
310 }
311 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
312 if (err)
313 goto err_ctlreg;
314 spromctl &= ~SSB_SPROMCTL_WE;
315 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
316 if (err)
317 goto err_ctlreg;
318 msleep(500);
b8b6069c
MB
319 pr_cont("100%% ]\n");
320 pr_notice("SPROM written\n");
61e115a5
MB
321
322 return 0;
323err_ctlreg:
b8b6069c 324 pr_err("Could not access SPROM control register.\n");
61e115a5
MB
325 return err;
326}
327
67d392c0
RM
328static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
329 u16 mask, u16 shift)
e861b98d
MB
330{
331 u16 v;
332 u8 gain;
333
67d392c0 334 v = in[SPOFF(offset)];
e861b98d
MB
335 gain = (v & mask) >> shift;
336 if (gain == 0xFF)
337 gain = 2; /* If unset use 2dBm */
338 if (sprom_revision == 1) {
339 /* Convert to Q5.2 */
340 gain <<= 2;
341 } else {
342 /* Q5.2 Fractional part is stored in 0xC0 */
343 gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
344 }
345
346 return (s8)gain;
347}
348
7e4235ac
HM
349static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
350{
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);
362}
363
c272ef44 364static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
61e115a5 365{
c272ef44 366 u16 loc[3];
61e115a5 367
31ce12fb 368 if (out->revision == 3) /* rev 3 moved MAC */
c272ef44 369 loc[0] = SSB_SPROM3_IL0MAC;
31ce12fb 370 else {
c272ef44
LF
371 loc[0] = SSB_SPROM1_IL0MAC;
372 loc[1] = SSB_SPROM1_ET0MAC;
373 loc[2] = SSB_SPROM1_ET1MAC;
374 }
e5652756 375 sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
31ce12fb 376 if (out->revision < 3) { /* only rev 1-2 have et0, et1 */
e5652756
JP
377 sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
378 sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
61e115a5 379 }
c272ef44
LF
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);
e861b98d
MB
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);
3623b266 386 SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
bf7d420b
HM
387 if (out->revision == 1)
388 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
389 SSB_SPROM1_BINF_CCODE_SHIFT);
e861b98d
MB
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);
c272ef44
LF
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);
7e4235ac 413
bf7d420b
HM
414 SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
415 SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
e861b98d
MB
416
417 /* Extract the antenna gain values. */
67d392c0
RM
418 out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
419 SSB_SPROM1_AGAIN,
420 SSB_SPROM1_AGAIN_BG,
421 SSB_SPROM1_AGAIN_BG_SHIFT);
422 out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
423 SSB_SPROM1_AGAIN,
424 SSB_SPROM1_AGAIN_A,
425 SSB_SPROM1_AGAIN_A_SHIFT);
7e4235ac
HM
426 if (out->revision >= 2)
427 sprom_extract_r23(out, in);
61e115a5
MB
428}
429
172c69a4
RM
430/* Revs 4 5 and 8 have partially shared layout */
431static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
432{
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);
441
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);
450
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);
459
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);
468}
469
095f695c 470static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
61e115a5 471{
6ad59343
RM
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
475 };
095f695c 476 u16 il0mac_offset;
6ad59343
RM
477 int i;
478
479 BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
480 ARRAY_SIZE(out->core_pwr_info));
c272ef44 481
095f695c
LF
482 if (out->revision == 4)
483 il0mac_offset = SSB_SPROM4_IL0MAC;
484 else
485 il0mac_offset = SSB_SPROM5_IL0MAC;
e5652756
JP
486
487 sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
488
c272ef44
LF
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);
673335c8 492 SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
3623b266 493 SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
095f695c 494 if (out->revision == 4) {
bf7d420b
HM
495 SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
496 SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
095f695c
LF
497 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
498 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
6d1d4ea4
RM
499 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
500 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
095f695c 501 } else {
bf7d420b
HM
502 SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
503 SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
095f695c
LF
504 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
505 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
6d1d4ea4
RM
506 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
507 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
095f695c 508 }
e861b98d
MB
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);
d3c319f9
LF
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);
095f695c
LF
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);
526 } else {
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);
533 }
e861b98d
MB
534
535 /* Extract the antenna gain values. */
6daf4321
RM
536 out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
537 SSB_SPROM4_AGAIN01,
538 SSB_SPROM4_AGAIN0,
539 SSB_SPROM4_AGAIN0_SHIFT);
540 out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
541 SSB_SPROM4_AGAIN01,
542 SSB_SPROM4_AGAIN1,
543 SSB_SPROM4_AGAIN1_SHIFT);
544 out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
545 SSB_SPROM4_AGAIN23,
546 SSB_SPROM4_AGAIN2,
547 SSB_SPROM4_AGAIN2_SHIFT);
548 out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
549 SSB_SPROM4_AGAIN23,
550 SSB_SPROM4_AGAIN3,
551 SSB_SPROM4_AGAIN3_SHIFT);
e861b98d 552
6ad59343
RM
553 /* Extract cores power info info */
554 for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
555 u16 o = pwr_info_offset[i];
556
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);
561
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);
566
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);
575
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);
588 }
589
172c69a4
RM
590 sprom_extract_r458(out, in);
591
c272ef44 592 /* TODO - get remaining rev 4 stuff needed */
61e115a5
MB
593}
594
6b1c7c67
MB
595static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
596{
597 int i;
e5652756 598 u16 o;
b0f70292
RM
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
602 };
603 BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
604 ARRAY_SIZE(out->core_pwr_info));
6b1c7c67
MB
605
606 /* extract the MAC address */
e5652756
JP
607 sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
608
673335c8 609 SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
3623b266 610 SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
bf7d420b
HM
611 SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
612 SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
6b1c7c67
MB
613 SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
614 SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
f679056b
GS
615 SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
616 SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
6b1c7c67
MB
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);
f679056b
GS
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);
6b1c7c67
MB
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);
f679056b
GS
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);
6b1c7c67
MB
676
677 /* Extract the antenna gain values. */
6daf4321
RM
678 out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
679 SSB_SPROM8_AGAIN01,
680 SSB_SPROM8_AGAIN0,
681 SSB_SPROM8_AGAIN0_SHIFT);
682 out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
683 SSB_SPROM8_AGAIN01,
684 SSB_SPROM8_AGAIN1,
685 SSB_SPROM8_AGAIN1_SHIFT);
686 out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
687 SSB_SPROM8_AGAIN23,
688 SSB_SPROM8_AGAIN2,
689 SSB_SPROM8_AGAIN2_SHIFT);
690 out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
691 SSB_SPROM8_AGAIN23,
692 SSB_SPROM8_AGAIN3,
693 SSB_SPROM8_AGAIN3_SHIFT);
6b1c7c67 694
b0f70292
RM
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);
702
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);
706
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);
715
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);
725 }
726
8a5ac6ec
RM
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);
738
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);
749
e2da4bd3
HM
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);
754
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);
761
762 SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
763
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);
768
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);
789
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);
794
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);
172c69a4
RM
807 sprom_extract_r458(out, in);
808
6b1c7c67
MB
809 /* TODO - get remaining rev 8 stuff needed */
810}
811
c272ef44
LF
812static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
813 const u16 *in, u16 size)
61e115a5
MB
814{
815 memset(out, 0, sizeof(*out));
816
c272ef44 817 out->revision = in[size - 1] & 0x00FF;
b8b6069c 818 pr_debug("SPROM revision %d detected\n", out->revision);
31ce12fb
LF
819 memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
820 memset(out->et1mac, 0xFF, 6);
54435f9e 821
61e115a5
MB
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. */
c272ef44 826 out->revision = 1;
b8b6069c 827 pr_debug("SPROM treated as revision %d\n", out->revision);
54435f9e
RM
828 }
829
830 switch (out->revision) {
831 case 1:
832 case 2:
833 case 3:
834 sprom_extract_r123(out, in);
835 break;
836 case 4:
837 case 5:
095f695c 838 sprom_extract_r45(out, in);
54435f9e
RM
839 break;
840 case 8:
841 sprom_extract_r8(out, in);
842 break;
843 default:
b8b6069c
MB
844 pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
845 out->revision);
54435f9e
RM
846 out->revision = 1;
847 sprom_extract_r123(out, in);
61e115a5
MB
848 }
849
4503183a
LF
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 */
854
61e115a5 855 return 0;
61e115a5
MB
856}
857
858static int ssb_pci_sprom_get(struct ssb_bus *bus,
859 struct ssb_sprom *sprom)
860{
ca4a0831 861 int err;
61e115a5
MB
862 u16 *buf;
863
d53cdbb9 864 if (!ssb_is_sprom_available(bus)) {
b8b6069c 865 pr_err("No SPROM available!\n");
d53cdbb9
JL
866 return -ENODEV;
867 }
25985edc 868 if (bus->chipco.dev) { /* can be unavailable! */
9d1ac34e
LF
869 /*
870 * get SPROM offset: SSB_SPROM_BASE1 except for
871 * chipcommon rev >= 31 or chip ID is 0x4312 and
872 * chipcommon status & 3 == 2
873 */
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;
879 else
880 bus->sprom_offset = SSB_SPROM_BASE1;
da1fdb02
CF
881 } else {
882 bus->sprom_offset = SSB_SPROM_BASE1;
883 }
b8b6069c 884 pr_debug("SPROM offset is 0x%x\n", bus->sprom_offset);
ea2db495 885
c272ef44 886 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
61e115a5 887 if (!buf)
ca4a0831 888 return -ENOMEM;
c272ef44 889 bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
61e115a5 890 sprom_do_read(bus, buf);
c272ef44 891 err = sprom_check_crc(buf, bus->sprom_size);
61e115a5 892 if (err) {
2afc4901
LF
893 /* try for a 440 byte SPROM - revision 4 and higher */
894 kfree(buf);
895 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
896 GFP_KERNEL);
897 if (!buf)
ca4a0831 898 return -ENOMEM;
2afc4901
LF
899 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
900 sprom_do_read(bus, buf);
901 err = sprom_check_crc(buf, bus->sprom_size);
e79c1ba8
MB
902 if (err) {
903 /* All CRC attempts failed.
904 * Maybe there is no SPROM on the device?
b3ae52b6
HM
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);
908 if (err) {
b8b6069c
MB
909 pr_warn("WARNING: Using fallback SPROM failed (err %d)\n",
910 err);
8052d724 911 goto out_free;
b3ae52b6 912 } else {
b8b6069c
MB
913 pr_debug("Using SPROM revision %d provided by platform\n",
914 sprom->revision);
e79c1ba8
MB
915 err = 0;
916 goto out_free;
917 }
b8b6069c 918 pr_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
e79c1ba8 919 }
61e115a5 920 }
c272ef44 921 err = sprom_extract(bus, sprom, buf, bus->sprom_size);
61e115a5 922
e79c1ba8 923out_free:
61e115a5 924 kfree(buf);
61e115a5
MB
925 return err;
926}
927
928static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
929 struct ssb_boardinfo *bi)
930{
115f9450
SS
931 bi->vendor = bus->host_pci->subsystem_vendor;
932 bi->type = bus->host_pci->subsystem_device;
61e115a5
MB
933}
934
935int ssb_pci_get_invariants(struct ssb_bus *bus,
936 struct ssb_init_invariants *iv)
937{
938 int err;
939
940 err = ssb_pci_sprom_get(bus, &iv->sprom);
941 if (err)
942 goto out;
943 ssb_pci_get_boardinfo(bus, &iv->boardinfo);
944
945out:
946 return err;
947}
948
61e115a5
MB
949static int ssb_pci_assert_buspower(struct ssb_bus *bus)
950{
951 if (likely(bus->powered_up))
952 return 0;
953
b8b6069c 954 pr_err("FATAL ERROR: Bus powered down while accessing PCI MMIO space\n");
61e115a5
MB
955 if (bus->power_warn_count <= 10) {
956 bus->power_warn_count++;
957 dump_stack();
958 }
959
960 return -ENODEV;
961}
61e115a5 962
ffc7689d
MB
963static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
964{
965 struct ssb_bus *bus = dev->bus;
966
967 if (unlikely(ssb_pci_assert_buspower(bus)))
968 return 0xFF;
969 if (unlikely(bus->mapped_device != dev)) {
970 if (unlikely(ssb_pci_switch_core(bus, dev)))
971 return 0xFF;
972 }
973 return ioread8(bus->mmio + offset);
974}
975
61e115a5
MB
976static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
977{
978 struct ssb_bus *bus = dev->bus;
979
980 if (unlikely(ssb_pci_assert_buspower(bus)))
981 return 0xFFFF;
982 if (unlikely(bus->mapped_device != dev)) {
983 if (unlikely(ssb_pci_switch_core(bus, dev)))
984 return 0xFFFF;
985 }
4b402c65 986 return ioread16(bus->mmio + offset);
61e115a5
MB
987}
988
989static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
990{
991 struct ssb_bus *bus = dev->bus;
992
993 if (unlikely(ssb_pci_assert_buspower(bus)))
994 return 0xFFFFFFFF;
995 if (unlikely(bus->mapped_device != dev)) {
996 if (unlikely(ssb_pci_switch_core(bus, dev)))
997 return 0xFFFFFFFF;
998 }
4b402c65 999 return ioread32(bus->mmio + offset);
61e115a5
MB
1000}
1001
d625a29b
MB
1002#ifdef CONFIG_SSB_BLOCKIO
1003static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
1004 size_t count, u16 offset, u8 reg_width)
1005{
1006 struct ssb_bus *bus = dev->bus;
1007 void __iomem *addr = bus->mmio + offset;
1008
1009 if (unlikely(ssb_pci_assert_buspower(bus)))
1010 goto error;
1011 if (unlikely(bus->mapped_device != dev)) {
1012 if (unlikely(ssb_pci_switch_core(bus, dev)))
1013 goto error;
1014 }
1015 switch (reg_width) {
1016 case sizeof(u8):
1017 ioread8_rep(addr, buffer, count);
1018 break;
1019 case sizeof(u16):
209b4375 1020 WARN_ON(count & 1);
d625a29b
MB
1021 ioread16_rep(addr, buffer, count >> 1);
1022 break;
1023 case sizeof(u32):
209b4375 1024 WARN_ON(count & 3);
d625a29b
MB
1025 ioread32_rep(addr, buffer, count >> 2);
1026 break;
1027 default:
209b4375 1028 WARN_ON(1);
d625a29b
MB
1029 }
1030
1031 return;
1032error:
1033 memset(buffer, 0xFF, count);
1034}
1035#endif /* CONFIG_SSB_BLOCKIO */
1036
ffc7689d
MB
1037static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
1038{
1039 struct ssb_bus *bus = dev->bus;
1040
1041 if (unlikely(ssb_pci_assert_buspower(bus)))
1042 return;
1043 if (unlikely(bus->mapped_device != dev)) {
1044 if (unlikely(ssb_pci_switch_core(bus, dev)))
1045 return;
1046 }
1047 iowrite8(value, bus->mmio + offset);
1048}
1049
61e115a5
MB
1050static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
1051{
1052 struct ssb_bus *bus = dev->bus;
1053
1054 if (unlikely(ssb_pci_assert_buspower(bus)))
1055 return;
1056 if (unlikely(bus->mapped_device != dev)) {
1057 if (unlikely(ssb_pci_switch_core(bus, dev)))
1058 return;
1059 }
4b402c65 1060 iowrite16(value, bus->mmio + offset);
61e115a5
MB
1061}
1062
1063static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1064{
1065 struct ssb_bus *bus = dev->bus;
1066
1067 if (unlikely(ssb_pci_assert_buspower(bus)))
1068 return;
1069 if (unlikely(bus->mapped_device != dev)) {
1070 if (unlikely(ssb_pci_switch_core(bus, dev)))
1071 return;
1072 }
4b402c65 1073 iowrite32(value, bus->mmio + offset);
61e115a5
MB
1074}
1075
d625a29b
MB
1076#ifdef CONFIG_SSB_BLOCKIO
1077static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1078 size_t count, u16 offset, u8 reg_width)
1079{
1080 struct ssb_bus *bus = dev->bus;
1081 void __iomem *addr = bus->mmio + offset;
1082
1083 if (unlikely(ssb_pci_assert_buspower(bus)))
1084 return;
1085 if (unlikely(bus->mapped_device != dev)) {
1086 if (unlikely(ssb_pci_switch_core(bus, dev)))
1087 return;
1088 }
1089 switch (reg_width) {
1090 case sizeof(u8):
1091 iowrite8_rep(addr, buffer, count);
1092 break;
1093 case sizeof(u16):
209b4375 1094 WARN_ON(count & 1);
d625a29b
MB
1095 iowrite16_rep(addr, buffer, count >> 1);
1096 break;
1097 case sizeof(u32):
209b4375 1098 WARN_ON(count & 3);
d625a29b
MB
1099 iowrite32_rep(addr, buffer, count >> 2);
1100 break;
1101 default:
209b4375 1102 WARN_ON(1);
d625a29b
MB
1103 }
1104}
1105#endif /* CONFIG_SSB_BLOCKIO */
1106
61e115a5
MB
1107/* Not "static", as it's used in main.c */
1108const struct ssb_bus_ops ssb_pci_ops = {
ffc7689d 1109 .read8 = ssb_pci_read8,
61e115a5
MB
1110 .read16 = ssb_pci_read16,
1111 .read32 = ssb_pci_read32,
ffc7689d 1112 .write8 = ssb_pci_write8,
61e115a5
MB
1113 .write16 = ssb_pci_write16,
1114 .write32 = ssb_pci_write32,
d625a29b
MB
1115#ifdef CONFIG_SSB_BLOCKIO
1116 .block_read = ssb_pci_block_read,
1117 .block_write = ssb_pci_block_write,
1118#endif
61e115a5
MB
1119};
1120
61e115a5
MB
1121static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1122 struct device_attribute *attr,
1123 char *buf)
1124{
1125 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1126 struct ssb_bus *bus;
61e115a5
MB
1127
1128 bus = ssb_pci_dev_to_bus(pdev);
1129 if (!bus)
e7ec2e32 1130 return -ENODEV;
61e115a5 1131
e7ec2e32 1132 return ssb_attr_sprom_show(bus, buf, sprom_do_read);
61e115a5
MB
1133}
1134
1135static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1136 struct device_attribute *attr,
1137 const char *buf, size_t count)
1138{
1139 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1140 struct ssb_bus *bus;
61e115a5
MB
1141
1142 bus = ssb_pci_dev_to_bus(pdev);
1143 if (!bus)
e7ec2e32 1144 return -ENODEV;
61e115a5 1145
e7ec2e32
MB
1146 return ssb_attr_sprom_store(bus, buf, count,
1147 sprom_check_crc, sprom_do_write);
61e115a5
MB
1148}
1149
1150static DEVICE_ATTR(ssb_sprom, 0600,
1151 ssb_pci_attr_sprom_show,
1152 ssb_pci_attr_sprom_store);
1153
1154void ssb_pci_exit(struct ssb_bus *bus)
1155{
1156 struct pci_dev *pdev;
1157
1158 if (bus->bustype != SSB_BUSTYPE_PCI)
1159 return;
1160
1161 pdev = bus->host_pci;
1162 device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1163}
1164
1165int ssb_pci_init(struct ssb_bus *bus)
1166{
1167 struct pci_dev *pdev;
1168 int err;
1169
1170 if (bus->bustype != SSB_BUSTYPE_PCI)
1171 return 0;
1172
1173 pdev = bus->host_pci;
e7ec2e32 1174 mutex_init(&bus->sprom_mutex);
61e115a5
MB
1175 err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1176 if (err)
1177 goto out;
1178
1179out:
1180 return err;
1181}