Root/drivers/ssb/pci.c

1/*
2 * Sonics Silicon Backplane PCI-Hostbus related functions.
3 *
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>
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
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>
23
24#include "ssb_private.h"
25
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:
59    ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
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
70    ssb_printk(KERN_INFO PFX
71           "Switching to %s core, index %d\n",
72           ssb_core_name(dev->id.coreid),
73           dev->core_index);
74#endif
75
76    spin_lock_irqsave(&bus->bar_lock, flags);
77    err = ssb_pci_switch_coreidx(bus, dev->core_index);
78    if (!err)
79        bus->mapped_device = dev;
80    spin_unlock_irqrestore(&bus->bar_lock, flags);
81
82    return err;
83}
84
85/* Enable/disable the on board crystal oscillator and/or PLL. */
86int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
87{
88    int err;
89    u32 in, out, outenable;
90    u16 pci_status;
91
92    if (bus->bustype != SSB_BUSTYPE_PCI)
93        return 0;
94
95    err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
96    if (err)
97        goto err_pci;
98    err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
99    if (err)
100        goto err_pci;
101    err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
102    if (err)
103        goto err_pci;
104
105    outenable |= what;
106
107    if (turn_on) {
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.
111         */
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)
117                    out |= SSB_GPIO_PLL;
118                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
119                if (err)
120                    goto err_pci;
121                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
122                                 outenable);
123                if (err)
124                    goto err_pci;
125                msleep(1);
126            }
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);
131                if (err)
132                    goto err_pci;
133                msleep(5);
134            }
135        }
136
137        err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
138        if (err)
139            goto err_pci;
140        pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
141        err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
142        if (err)
143            goto err_pci;
144    } else {
145        if (what & SSB_GPIO_XTAL) {
146            /* Turn the crystal off */
147            out &= ~SSB_GPIO_XTAL;
148        }
149        if (what & SSB_GPIO_PLL) {
150            /* Turn the PLL off */
151            out |= SSB_GPIO_PLL;
152        }
153        err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
154        if (err)
155            goto err_pci;
156        err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
157        if (err)
158            goto err_pci;
159    }
160
161out:
162    return err;
163
164err_pci:
165    printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n");
166    err = -EBUSY;
167    goto out;
168}
169
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)
180
181
182static inline u8 ssb_crc8(u8 crc, u8 data)
183{
184    /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
185    static const u8 t[] = {
186        0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
187        0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
188        0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
189        0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
190        0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
191        0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
192        0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
193        0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
194        0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
195        0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
196        0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
197        0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
198        0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
199        0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
200        0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
201        0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
202        0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
203        0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
204        0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
205        0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
206        0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
207        0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
208        0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
209        0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
210        0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
211        0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
212        0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
213        0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
214        0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
215        0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
216        0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
217        0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
218    };
219    return t[crc ^ data];
220}
221
222static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
223{
224    int word;
225    u8 crc = 0xFF;
226
227    for (word = 0; word < size - 1; word++) {
228        crc = ssb_crc8(crc, sprom[word] & 0x00FF);
229        crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
230    }
231    crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
232    crc ^= 0xFF;
233
234    return crc;
235}
236
237static int sprom_check_crc(const u16 *sprom, size_t size)
238{
239    u8 crc;
240    u8 expected_crc;
241    u16 tmp;
242
243    crc = ssb_sprom_crc(sprom, size);
244    tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
245    expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
246    if (crc != expected_crc)
247        return -EPROTO;
248
249    return 0;
250}
251
252static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
253{
254    int i;
255
256    for (i = 0; i < bus->sprom_size; i++)
257        sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
258
259    return 0;
260}
261
262static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
263{
264    struct pci_dev *pdev = bus->host_pci;
265    int i, err;
266    u32 spromctl;
267    u16 size = bus->sprom_size;
268
269    ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
270    err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
271    if (err)
272        goto err_ctlreg;
273    spromctl |= SSB_SPROMCTL_WE;
274    err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
275    if (err)
276        goto err_ctlreg;
277    ssb_printk(KERN_NOTICE PFX "[ 0%%");
278    msleep(500);
279    for (i = 0; i < size; i++) {
280        if (i == size / 4)
281            ssb_printk("25%%");
282        else if (i == size / 2)
283            ssb_printk("50%%");
284        else if (i == (size * 3) / 4)
285            ssb_printk("75%%");
286        else if (i % 2)
287            ssb_printk(".");
288        writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
289        mmiowb();
290        msleep(20);
291    }
292    err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
293    if (err)
294        goto err_ctlreg;
295    spromctl &= ~SSB_SPROMCTL_WE;
296    err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
297    if (err)
298        goto err_ctlreg;
299    msleep(500);
300    ssb_printk("100%% ]\n");
301    ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
302
303    return 0;
304err_ctlreg:
305    ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
306    return err;
307}
308
309static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
310                   u16 mask, u16 shift)
311{
312    u16 v;
313    u8 gain;
314
315    v = in[SPOFF(SSB_SPROM1_AGAIN)];
316    gain = (v & mask) >> shift;
317    if (gain == 0xFF)
318        gain = 2; /* If unset use 2dBm */
319    if (sprom_revision == 1) {
320        /* Convert to Q5.2 */
321        gain <<= 2;
322    } else {
323        /* Q5.2 Fractional part is stored in 0xC0 */
324        gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
325    }
326
327    return (s8)gain;
328}
329
330static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
331{
332    int i;
333    u16 v;
334    u16 loc[3];
335
336    if (out->revision == 3) /* rev 3 moved MAC */
337        loc[0] = SSB_SPROM3_IL0MAC;
338    else {
339        loc[0] = SSB_SPROM1_IL0MAC;
340        loc[1] = SSB_SPROM1_ET0MAC;
341        loc[2] = SSB_SPROM1_ET1MAC;
342    }
343    for (i = 0; i < 3; i++) {
344        v = in[SPOFF(loc[0]) + i];
345        *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
346    }
347    if (out->revision < 3) { /* only rev 1-2 have et0, et1 */
348        for (i = 0; i < 3; i++) {
349            v = in[SPOFF(loc[1]) + i];
350            *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
351        }
352        for (i = 0; i < 3; i++) {
353            v = in[SPOFF(loc[2]) + i];
354            *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
355        }
356    }
357    SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
358    SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
359         SSB_SPROM1_ETHPHY_ET1A_SHIFT);
360    SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
361    SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
362    SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
363    SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
364         SSB_SPROM1_BINF_CCODE_SHIFT);
365    SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
366         SSB_SPROM1_BINF_ANTA_SHIFT);
367    SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
368         SSB_SPROM1_BINF_ANTBG_SHIFT);
369    SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
370    SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
371    SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
372    SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
373    SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
374    SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
375    SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
376    SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
377         SSB_SPROM1_GPIOA_P1_SHIFT);
378    SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
379    SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
380         SSB_SPROM1_GPIOB_P3_SHIFT);
381    SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
382         SSB_SPROM1_MAXPWR_A_SHIFT);
383    SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
384    SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
385         SSB_SPROM1_ITSSI_A_SHIFT);
386    SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
387    SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
388    if (out->revision >= 2)
389        SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
390
391    /* Extract the antenna gain values. */
392    out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
393                            SSB_SPROM1_AGAIN_BG,
394                            SSB_SPROM1_AGAIN_BG_SHIFT);
395    out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
396                            SSB_SPROM1_AGAIN_A,
397                            SSB_SPROM1_AGAIN_A_SHIFT);
398}
399
400/* Revs 4 5 and 8 have partially shared layout */
401static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
402{
403    SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
404         SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
405    SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
406         SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
407    SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
408         SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
409    SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
410         SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
411
412    SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
413         SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
414    SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
415         SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
416    SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
417         SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
418    SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
419         SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
420
421    SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
422         SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
423    SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
424         SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
425    SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
426         SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
427    SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
428         SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
429
430    SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
431         SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
432    SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
433         SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
434    SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
435         SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
436    SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
437         SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
438}
439
440static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
441{
442    int i;
443    u16 v;
444    u16 il0mac_offset;
445
446    if (out->revision == 4)
447        il0mac_offset = SSB_SPROM4_IL0MAC;
448    else
449        il0mac_offset = SSB_SPROM5_IL0MAC;
450    /* extract the MAC address */
451    for (i = 0; i < 3; i++) {
452        v = in[SPOFF(il0mac_offset) + i];
453        *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
454    }
455    SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
456    SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
457         SSB_SPROM4_ETHPHY_ET1A_SHIFT);
458    if (out->revision == 4) {
459        SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
460        SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
461        SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
462        SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
463        SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
464    } else {
465        SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
466        SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
467        SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
468        SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
469        SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
470    }
471    SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
472         SSB_SPROM4_ANTAVAIL_A_SHIFT);
473    SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
474         SSB_SPROM4_ANTAVAIL_BG_SHIFT);
475    SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
476    SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
477         SSB_SPROM4_ITSSI_BG_SHIFT);
478    SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
479    SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
480         SSB_SPROM4_ITSSI_A_SHIFT);
481    if (out->revision == 4) {
482        SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
483        SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
484             SSB_SPROM4_GPIOA_P1_SHIFT);
485        SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
486        SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
487             SSB_SPROM4_GPIOB_P3_SHIFT);
488    } else {
489        SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
490        SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
491             SSB_SPROM5_GPIOA_P1_SHIFT);
492        SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
493        SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
494             SSB_SPROM5_GPIOB_P3_SHIFT);
495    }
496
497    /* Extract the antenna gain values. */
498    SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
499         SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
500    SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
501         SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
502    SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
503         SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
504    SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
505         SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
506
507    sprom_extract_r458(out, in);
508
509    /* TODO - get remaining rev 4 stuff needed */
510}
511
512static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
513{
514    int i;
515    u16 v, o;
516    u16 pwr_info_offset[] = {
517        SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
518        SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
519    };
520    BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
521            ARRAY_SIZE(out->core_pwr_info));
522
523    /* extract the MAC address */
524    for (i = 0; i < 3; i++) {
525        v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
526        *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
527    }
528    SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
529    SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
530    SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
531    SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
532    SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
533    SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
534         SSB_SPROM8_ANTAVAIL_A_SHIFT);
535    SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
536         SSB_SPROM8_ANTAVAIL_BG_SHIFT);
537    SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
538    SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
539         SSB_SPROM8_ITSSI_BG_SHIFT);
540    SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
541    SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
542         SSB_SPROM8_ITSSI_A_SHIFT);
543    SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
544    SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
545         SSB_SPROM8_MAXP_AL_SHIFT);
546    SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
547    SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
548         SSB_SPROM8_GPIOA_P1_SHIFT);
549    SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
550    SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
551         SSB_SPROM8_GPIOB_P3_SHIFT);
552    SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
553    SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
554         SSB_SPROM8_TRI5G_SHIFT);
555    SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
556    SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
557         SSB_SPROM8_TRI5GH_SHIFT);
558    SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
559    SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
560         SSB_SPROM8_RXPO5G_SHIFT);
561    SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
562    SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
563         SSB_SPROM8_RSSISMC2G_SHIFT);
564    SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
565         SSB_SPROM8_RSSISAV2G_SHIFT);
566    SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
567         SSB_SPROM8_BXA2G_SHIFT);
568    SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
569    SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
570         SSB_SPROM8_RSSISMC5G_SHIFT);
571    SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
572         SSB_SPROM8_RSSISAV5G_SHIFT);
573    SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
574         SSB_SPROM8_BXA5G_SHIFT);
575    SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
576    SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
577    SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
578    SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
579    SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
580    SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
581    SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
582    SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
583    SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
584    SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
585    SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
586    SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
587    SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
588    SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
589    SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
590    SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
591    SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
592
593    /* Extract the antenna gain values. */
594    SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
595         SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
596    SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
597         SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
598    SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
599         SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
600    SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
601         SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
602
603    /* Extract cores power info info */
604    for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
605        o = pwr_info_offset[i];
606        SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
607            SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
608        SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
609            SSB_SPROM8_2G_MAXP, 0);
610
611        SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
612        SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
613        SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
614
615        SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
616            SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
617        SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
618            SSB_SPROM8_5G_MAXP, 0);
619        SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
620            SSB_SPROM8_5GH_MAXP, 0);
621        SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
622            SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
623
624        SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
625        SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
626        SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
627        SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
628        SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
629        SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
630        SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
631        SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
632        SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
633    }
634
635    /* Extract FEM info */
636    SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
637        SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
638    SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
639        SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
640    SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
641        SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
642    SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
643        SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
644    SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
645        SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
646
647    SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
648        SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
649    SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
650        SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
651    SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
652        SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
653    SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
654        SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
655    SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
656        SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
657
658    sprom_extract_r458(out, in);
659
660    /* TODO - get remaining rev 8 stuff needed */
661}
662
663static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
664             const u16 *in, u16 size)
665{
666    memset(out, 0, sizeof(*out));
667
668    out->revision = in[size - 1] & 0x00FF;
669    ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
670    memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
671    memset(out->et1mac, 0xFF, 6);
672
673    if ((bus->chip_id & 0xFF00) == 0x4400) {
674        /* Workaround: The BCM44XX chip has a stupid revision
675         * number stored in the SPROM.
676         * Always extract r1. */
677        out->revision = 1;
678        ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
679    }
680
681    switch (out->revision) {
682    case 1:
683    case 2:
684    case 3:
685        sprom_extract_r123(out, in);
686        break;
687    case 4:
688    case 5:
689        sprom_extract_r45(out, in);
690        break;
691    case 8:
692        sprom_extract_r8(out, in);
693        break;
694    default:
695        ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
696               " revision %d detected. Will extract"
697               " v1\n", out->revision);
698        out->revision = 1;
699        sprom_extract_r123(out, in);
700    }
701
702    if (out->boardflags_lo == 0xFFFF)
703        out->boardflags_lo = 0; /* per specs */
704    if (out->boardflags_hi == 0xFFFF)
705        out->boardflags_hi = 0; /* per specs */
706
707    return 0;
708}
709
710static int ssb_pci_sprom_get(struct ssb_bus *bus,
711                 struct ssb_sprom *sprom)
712{
713    int err;
714    u16 *buf;
715
716    if (!ssb_is_sprom_available(bus)) {
717        ssb_printk(KERN_ERR PFX "No SPROM available!\n");
718        return -ENODEV;
719    }
720    if (bus->chipco.dev) { /* can be unavailable! */
721        /*
722         * get SPROM offset: SSB_SPROM_BASE1 except for
723         * chipcommon rev >= 31 or chip ID is 0x4312 and
724         * chipcommon status & 3 == 2
725         */
726        if (bus->chipco.dev->id.revision >= 31)
727            bus->sprom_offset = SSB_SPROM_BASE31;
728        else if (bus->chip_id == 0x4312 &&
729             (bus->chipco.status & 0x03) == 2)
730            bus->sprom_offset = SSB_SPROM_BASE31;
731        else
732            bus->sprom_offset = SSB_SPROM_BASE1;
733    } else {
734        bus->sprom_offset = SSB_SPROM_BASE1;
735    }
736    ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
737
738    buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
739    if (!buf)
740        return -ENOMEM;
741    bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
742    sprom_do_read(bus, buf);
743    err = sprom_check_crc(buf, bus->sprom_size);
744    if (err) {
745        /* try for a 440 byte SPROM - revision 4 and higher */
746        kfree(buf);
747        buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
748                  GFP_KERNEL);
749        if (!buf)
750            return -ENOMEM;
751        bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
752        sprom_do_read(bus, buf);
753        err = sprom_check_crc(buf, bus->sprom_size);
754        if (err) {
755            /* All CRC attempts failed.
756             * Maybe there is no SPROM on the device?
757             * Now we ask the arch code if there is some sprom
758             * available for this device in some other storage */
759            err = ssb_fill_sprom_with_fallback(bus, sprom);
760            if (err) {
761                ssb_printk(KERN_WARNING PFX "WARNING: Using"
762                       " fallback SPROM failed (err %d)\n",
763                       err);
764            } else {
765                ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
766                        " revision %d provided by"
767                        " platform.\n", sprom->revision);
768                err = 0;
769                goto out_free;
770            }
771            ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
772                   " SPROM CRC (corrupt SPROM)\n");
773        }
774    }
775    err = sprom_extract(bus, sprom, buf, bus->sprom_size);
776
777out_free:
778    kfree(buf);
779    return err;
780}
781
782static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
783                  struct ssb_boardinfo *bi)
784{
785    bi->vendor = bus->host_pci->subsystem_vendor;
786    bi->type = bus->host_pci->subsystem_device;
787    bi->rev = bus->host_pci->revision;
788}
789
790int ssb_pci_get_invariants(struct ssb_bus *bus,
791               struct ssb_init_invariants *iv)
792{
793    int err;
794
795    err = ssb_pci_sprom_get(bus, &iv->sprom);
796    if (err)
797        goto out;
798    ssb_pci_get_boardinfo(bus, &iv->boardinfo);
799
800out:
801    return err;
802}
803
804#ifdef CONFIG_SSB_DEBUG
805static int ssb_pci_assert_buspower(struct ssb_bus *bus)
806{
807    if (likely(bus->powered_up))
808        return 0;
809
810    printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
811           "while accessing PCI MMIO space\n");
812    if (bus->power_warn_count <= 10) {
813        bus->power_warn_count++;
814        dump_stack();
815    }
816
817    return -ENODEV;
818}
819#else /* DEBUG */
820static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
821{
822    return 0;
823}
824#endif /* DEBUG */
825
826static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
827{
828    struct ssb_bus *bus = dev->bus;
829
830    if (unlikely(ssb_pci_assert_buspower(bus)))
831        return 0xFF;
832    if (unlikely(bus->mapped_device != dev)) {
833        if (unlikely(ssb_pci_switch_core(bus, dev)))
834            return 0xFF;
835    }
836    return ioread8(bus->mmio + offset);
837}
838
839static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
840{
841    struct ssb_bus *bus = dev->bus;
842
843    if (unlikely(ssb_pci_assert_buspower(bus)))
844        return 0xFFFF;
845    if (unlikely(bus->mapped_device != dev)) {
846        if (unlikely(ssb_pci_switch_core(bus, dev)))
847            return 0xFFFF;
848    }
849    return ioread16(bus->mmio + offset);
850}
851
852static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
853{
854    struct ssb_bus *bus = dev->bus;
855
856    if (unlikely(ssb_pci_assert_buspower(bus)))
857        return 0xFFFFFFFF;
858    if (unlikely(bus->mapped_device != dev)) {
859        if (unlikely(ssb_pci_switch_core(bus, dev)))
860            return 0xFFFFFFFF;
861    }
862    return ioread32(bus->mmio + offset);
863}
864
865#ifdef CONFIG_SSB_BLOCKIO
866static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
867                   size_t count, u16 offset, u8 reg_width)
868{
869    struct ssb_bus *bus = dev->bus;
870    void __iomem *addr = bus->mmio + offset;
871
872    if (unlikely(ssb_pci_assert_buspower(bus)))
873        goto error;
874    if (unlikely(bus->mapped_device != dev)) {
875        if (unlikely(ssb_pci_switch_core(bus, dev)))
876            goto error;
877    }
878    switch (reg_width) {
879    case sizeof(u8):
880        ioread8_rep(addr, buffer, count);
881        break;
882    case sizeof(u16):
883        SSB_WARN_ON(count & 1);
884        ioread16_rep(addr, buffer, count >> 1);
885        break;
886    case sizeof(u32):
887        SSB_WARN_ON(count & 3);
888        ioread32_rep(addr, buffer, count >> 2);
889        break;
890    default:
891        SSB_WARN_ON(1);
892    }
893
894    return;
895error:
896    memset(buffer, 0xFF, count);
897}
898#endif /* CONFIG_SSB_BLOCKIO */
899
900static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
901{
902    struct ssb_bus *bus = dev->bus;
903
904    if (unlikely(ssb_pci_assert_buspower(bus)))
905        return;
906    if (unlikely(bus->mapped_device != dev)) {
907        if (unlikely(ssb_pci_switch_core(bus, dev)))
908            return;
909    }
910    iowrite8(value, bus->mmio + offset);
911}
912
913static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
914{
915    struct ssb_bus *bus = dev->bus;
916
917    if (unlikely(ssb_pci_assert_buspower(bus)))
918        return;
919    if (unlikely(bus->mapped_device != dev)) {
920        if (unlikely(ssb_pci_switch_core(bus, dev)))
921            return;
922    }
923    iowrite16(value, bus->mmio + offset);
924}
925
926static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
927{
928    struct ssb_bus *bus = dev->bus;
929
930    if (unlikely(ssb_pci_assert_buspower(bus)))
931        return;
932    if (unlikely(bus->mapped_device != dev)) {
933        if (unlikely(ssb_pci_switch_core(bus, dev)))
934            return;
935    }
936    iowrite32(value, bus->mmio + offset);
937}
938
939#ifdef CONFIG_SSB_BLOCKIO
940static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
941                size_t count, u16 offset, u8 reg_width)
942{
943    struct ssb_bus *bus = dev->bus;
944    void __iomem *addr = bus->mmio + offset;
945
946    if (unlikely(ssb_pci_assert_buspower(bus)))
947        return;
948    if (unlikely(bus->mapped_device != dev)) {
949        if (unlikely(ssb_pci_switch_core(bus, dev)))
950            return;
951    }
952    switch (reg_width) {
953    case sizeof(u8):
954        iowrite8_rep(addr, buffer, count);
955        break;
956    case sizeof(u16):
957        SSB_WARN_ON(count & 1);
958        iowrite16_rep(addr, buffer, count >> 1);
959        break;
960    case sizeof(u32):
961        SSB_WARN_ON(count & 3);
962        iowrite32_rep(addr, buffer, count >> 2);
963        break;
964    default:
965        SSB_WARN_ON(1);
966    }
967}
968#endif /* CONFIG_SSB_BLOCKIO */
969
970/* Not "static", as it's used in main.c */
971const struct ssb_bus_ops ssb_pci_ops = {
972    .read8 = ssb_pci_read8,
973    .read16 = ssb_pci_read16,
974    .read32 = ssb_pci_read32,
975    .write8 = ssb_pci_write8,
976    .write16 = ssb_pci_write16,
977    .write32 = ssb_pci_write32,
978#ifdef CONFIG_SSB_BLOCKIO
979    .block_read = ssb_pci_block_read,
980    .block_write = ssb_pci_block_write,
981#endif
982};
983
984static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
985                       struct device_attribute *attr,
986                       char *buf)
987{
988    struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
989    struct ssb_bus *bus;
990
991    bus = ssb_pci_dev_to_bus(pdev);
992    if (!bus)
993        return -ENODEV;
994
995    return ssb_attr_sprom_show(bus, buf, sprom_do_read);
996}
997
998static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
999                    struct device_attribute *attr,
1000                    const char *buf, size_t count)
1001{
1002    struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1003    struct ssb_bus *bus;
1004
1005    bus = ssb_pci_dev_to_bus(pdev);
1006    if (!bus)
1007        return -ENODEV;
1008
1009    return ssb_attr_sprom_store(bus, buf, count,
1010                    sprom_check_crc, sprom_do_write);
1011}
1012
1013static DEVICE_ATTR(ssb_sprom, 0600,
1014           ssb_pci_attr_sprom_show,
1015           ssb_pci_attr_sprom_store);
1016
1017void ssb_pci_exit(struct ssb_bus *bus)
1018{
1019    struct pci_dev *pdev;
1020
1021    if (bus->bustype != SSB_BUSTYPE_PCI)
1022        return;
1023
1024    pdev = bus->host_pci;
1025    device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1026}
1027
1028int ssb_pci_init(struct ssb_bus *bus)
1029{
1030    struct pci_dev *pdev;
1031    int err;
1032
1033    if (bus->bustype != SSB_BUSTYPE_PCI)
1034        return 0;
1035
1036    pdev = bus->host_pci;
1037    mutex_init(&bus->sprom_mutex);
1038    err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1039    if (err)
1040        goto out;
1041
1042out:
1043    return err;
1044}
1045

Archive Download this file



interactive