OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [ssb/] [pci.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Sonics Silicon Backplane PCI-Hostbus related functions.
3
 *
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>
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/pci.h>
21
#include <linux/delay.h>
22
 
23
#include "ssb_private.h"
24
 
25
 
26
/* Define the following to 1 to enable a printk on each coreswitch. */
27
#define SSB_VERBOSE_PCICORESWITCH_DEBUG         0
28
 
29
 
30
/* Lowlevel coreswitching */
31
int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
32
{
33
        int err;
34
        int attempts = 0;
35
        u32 cur_core;
36
 
37
        while (1) {
38
                err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
39
                                             (coreidx * SSB_CORE_SIZE)
40
                                             + SSB_ENUM_BASE);
41
                if (err)
42
                        goto error;
43
                err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
44
                                            &cur_core);
45
                if (err)
46
                        goto error;
47
                cur_core = (cur_core - SSB_ENUM_BASE)
48
                           / SSB_CORE_SIZE;
49
                if (cur_core == coreidx)
50
                        break;
51
 
52
                if (attempts++ > SSB_BAR0_MAX_RETRIES)
53
                        goto error;
54
                udelay(10);
55
        }
56
        return 0;
57
error:
58
        ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
59
        return -ENODEV;
60
}
61
 
62
int ssb_pci_switch_core(struct ssb_bus *bus,
63
                        struct ssb_device *dev)
64
{
65
        int err;
66
        unsigned long flags;
67
 
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),
72
                   dev->core_index);
73
#endif
74
 
75
        spin_lock_irqsave(&bus->bar_lock, flags);
76
        err = ssb_pci_switch_coreidx(bus, dev->core_index);
77
        if (!err)
78
                bus->mapped_device = dev;
79
        spin_unlock_irqrestore(&bus->bar_lock, flags);
80
 
81
        return err;
82
}
83
 
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)
86
{
87
        int err;
88
        u32 in, out, outenable;
89
        u16 pci_status;
90
 
91
        if (bus->bustype != SSB_BUSTYPE_PCI)
92
                return 0;
93
 
94
        err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
95
        if (err)
96
                goto err_pci;
97
        err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
98
        if (err)
99
                goto err_pci;
100
        err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
101
        if (err)
102
                goto err_pci;
103
 
104
        outenable |= what;
105
 
106
        if (turn_on) {
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.
110
                 */
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)
116
                                        out |= SSB_GPIO_PLL;
117
                                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
118
                                if (err)
119
                                        goto err_pci;
120
                                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
121
                                                             outenable);
122
                                if (err)
123
                                        goto err_pci;
124
                                msleep(1);
125
                        }
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);
130
                                if (err)
131
                                        goto err_pci;
132
                                msleep(5);
133
                        }
134
                }
135
 
136
                err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
137
                if (err)
138
                        goto err_pci;
139
                pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
140
                err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
141
                if (err)
142
                        goto err_pci;
143
        } else {
144
                if (what & SSB_GPIO_XTAL) {
145
                        /* Turn the crystal off */
146
                        out &= ~SSB_GPIO_XTAL;
147
                }
148
                if (what & SSB_GPIO_PLL) {
149
                        /* Turn the PLL off */
150
                        out |= SSB_GPIO_PLL;
151
                }
152
                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
153
                if (err)
154
                        goto err_pci;
155
                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
156
                if (err)
157
                        goto err_pci;
158
        }
159
 
160
out:
161
        return err;
162
 
163
err_pci:
164
        printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n");
165
        err = -EBUSY;
166
        goto out;
167
}
168
 
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))
174
 
175
static inline u8 ssb_crc8(u8 crc, u8 data)
176
{
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,
211
        };
212
        return t[crc ^ data];
213
}
214
 
215
static u8 ssb_sprom_crc(const u16 *sprom)
216
{
217
        int word;
218
        u8 crc = 0xFF;
219
 
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);
223
        }
224
        crc = ssb_crc8(crc, sprom[SPOFF(SSB_SPROM_REVISION)] & 0x00FF);
225
        crc ^= 0xFF;
226
 
227
        return crc;
228
}
229
 
230
static int sprom_check_crc(const u16 *sprom)
231
{
232
        u8 crc;
233
        u8 expected_crc;
234
        u16 tmp;
235
 
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)
240
                return -EPROTO;
241
 
242
        return 0;
243
}
244
 
245
static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
246
{
247
        int i;
248
 
249
        for (i = 0; i < SSB_SPROMSIZE_WORDS; i++)
250
                sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2));
251
}
252
 
253
static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
254
{
255
        struct pci_dev *pdev = bus->host_pci;
256
        int i, err;
257
        u32 spromctl;
258
 
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);
261
        if (err)
262
                goto err_ctlreg;
263
        spromctl |= SSB_SPROMCTL_WE;
264
        err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
265
        if (err)
266
                goto err_ctlreg;
267
        ssb_printk(KERN_NOTICE PFX "[ 0%%");
268
        msleep(500);
269
        for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
270
                if (i == SSB_SPROMSIZE_WORDS / 4)
271
                        ssb_printk("25%%");
272
                else if (i == SSB_SPROMSIZE_WORDS / 2)
273
                        ssb_printk("50%%");
274
                else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3)
275
                        ssb_printk("75%%");
276
                else if (i % 2)
277
                        ssb_printk(".");
278
                writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
279
                mmiowb();
280
                msleep(20);
281
        }
282
        err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
283
        if (err)
284
                goto err_ctlreg;
285
        spromctl &= ~SSB_SPROMCTL_WE;
286
        err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
287
        if (err)
288
                goto err_ctlreg;
289
        msleep(500);
290
        ssb_printk("100%% ]\n");
291
        ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
292
 
293
        return 0;
294
err_ctlreg:
295
        ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
296
        return err;
297
}
298
 
299
static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)
300
{
301
        int i;
302
        u16 v;
303
 
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);
310
        }
311
        for (i = 0; i < 3; i++) {
312
                v = in[SPOFF(SSB_SPROM1_ET0MAC) + i];
313
                *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
314
        }
315
        for (i = 0; i < 3; i++) {
316
                v = in[SPOFF(SSB_SPROM1_ET1MAC) + i];
317
                *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
318
        }
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);
356
        }
357
}
358
 
359
static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in)
360
{
361
        int i;
362
        u16 v;
363
 
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);
378
        }
379
}
380
 
381
static void sprom_extract_r3(struct ssb_sprom_r3 *out, const u16 *in)
382
{
383
        out->ofdmapo  = (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0xFF00) >> 8;
384
        out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0x00FF) << 8;
385
        out->ofdmapo <<= 16;
386
        out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0xFF00) >> 8;
387
        out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0x00FF) << 8;
388
 
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;
394
 
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;
400
 
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);
412
 
413
        out->ofdmgpo  = (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0xFF00) >> 8;
414
        out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0x00FF) << 8;
415
        out->ofdmgpo <<= 16;
416
        out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0xFF00) >> 8;
417
        out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0x00FF) << 8;
418
}
419
 
420
static int sprom_extract(struct ssb_bus *bus,
421
                         struct ssb_sprom *out, const u16 *in)
422
{
423
        memset(out, 0, sizeof(*out));
424
 
425
        SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0);
426
        SPEX(crc, SSB_SPROM_REVISION, SSB_SPROM_REVISION_CRC,
427
             SSB_SPROM_REVISION_CRC_SHIFT);
428
 
429
        if ((bus->chip_id & 0xFF00) == 0x4400) {
430
                /* Workaround: The BCM44XX chip has a stupid revision
431
                 * number stored in the SPROM.
432
                 * Always extract r1. */
433
                sprom_extract_r1(&out->r1, in);
434
        } else {
435
                if (out->revision == 0)
436
                        goto unsupported;
437
                if (out->revision >= 1 && out->revision <= 3)
438
                        sprom_extract_r1(&out->r1, in);
439
                if (out->revision >= 2 && out->revision <= 3)
440
                        sprom_extract_r2(&out->r2, in);
441
                if (out->revision == 3)
442
                        sprom_extract_r3(&out->r3, in);
443
                if (out->revision >= 4)
444
                        goto unsupported;
445
        }
446
 
447
        return 0;
448
unsupported:
449
        ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
450
                   "detected. Will extract v1\n", out->revision);
451
        sprom_extract_r1(&out->r1, in);
452
        return 0;
453
}
454
 
455
static int ssb_pci_sprom_get(struct ssb_bus *bus,
456
                             struct ssb_sprom *sprom)
457
{
458
        int err = -ENOMEM;
459
        u16 *buf;
460
 
461
        buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
462
        if (!buf)
463
                goto out;
464
        sprom_do_read(bus, buf);
465
        err = sprom_check_crc(buf);
466
        if (err) {
467
                ssb_printk(KERN_WARNING PFX
468
                           "WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
469
        }
470
        err = sprom_extract(bus, sprom, buf);
471
 
472
        kfree(buf);
473
out:
474
        return err;
475
}
476
 
477
static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
478
                                  struct ssb_boardinfo *bi)
479
{
480
        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
481
                             &bi->vendor);
482
        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
483
                             &bi->type);
484
        pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
485
                             &bi->rev);
486
}
487
 
488
int ssb_pci_get_invariants(struct ssb_bus *bus,
489
                           struct ssb_init_invariants *iv)
490
{
491
        int err;
492
 
493
        err = ssb_pci_sprom_get(bus, &iv->sprom);
494
        if (err)
495
                goto out;
496
        ssb_pci_get_boardinfo(bus, &iv->boardinfo);
497
 
498
out:
499
        return err;
500
}
501
 
502
#ifdef CONFIG_SSB_DEBUG
503
static int ssb_pci_assert_buspower(struct ssb_bus *bus)
504
{
505
        if (likely(bus->powered_up))
506
                return 0;
507
 
508
        printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
509
               "while accessing PCI MMIO space\n");
510
        if (bus->power_warn_count <= 10) {
511
                bus->power_warn_count++;
512
                dump_stack();
513
        }
514
 
515
        return -ENODEV;
516
}
517
#else /* DEBUG */
518
static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
519
{
520
        return 0;
521
}
522
#endif /* DEBUG */
523
 
524
static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
525
{
526
        struct ssb_bus *bus = dev->bus;
527
 
528
        if (unlikely(ssb_pci_assert_buspower(bus)))
529
                return 0xFFFF;
530
        if (unlikely(bus->mapped_device != dev)) {
531
                if (unlikely(ssb_pci_switch_core(bus, dev)))
532
                        return 0xFFFF;
533
        }
534
        return ioread16(bus->mmio + offset);
535
}
536
 
537
static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
538
{
539
        struct ssb_bus *bus = dev->bus;
540
 
541
        if (unlikely(ssb_pci_assert_buspower(bus)))
542
                return 0xFFFFFFFF;
543
        if (unlikely(bus->mapped_device != dev)) {
544
                if (unlikely(ssb_pci_switch_core(bus, dev)))
545
                        return 0xFFFFFFFF;
546
        }
547
        return ioread32(bus->mmio + offset);
548
}
549
 
550
static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
551
{
552
        struct ssb_bus *bus = dev->bus;
553
 
554
        if (unlikely(ssb_pci_assert_buspower(bus)))
555
                return;
556
        if (unlikely(bus->mapped_device != dev)) {
557
                if (unlikely(ssb_pci_switch_core(bus, dev)))
558
                        return;
559
        }
560
        iowrite16(value, bus->mmio + offset);
561
}
562
 
563
static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
564
{
565
        struct ssb_bus *bus = dev->bus;
566
 
567
        if (unlikely(ssb_pci_assert_buspower(bus)))
568
                return;
569
        if (unlikely(bus->mapped_device != dev)) {
570
                if (unlikely(ssb_pci_switch_core(bus, dev)))
571
                        return;
572
        }
573
        iowrite32(value, bus->mmio + offset);
574
}
575
 
576
/* Not "static", as it's used in main.c */
577
const struct ssb_bus_ops ssb_pci_ops = {
578
        .read16         = ssb_pci_read16,
579
        .read32         = ssb_pci_read32,
580
        .write16        = ssb_pci_write16,
581
        .write32        = ssb_pci_write32,
582
};
583
 
584
static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
585
{
586
        int i, pos = 0;
587
 
588
        for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
589
                pos += snprintf(buf + pos, buf_len - pos - 1,
590
                                "%04X", swab16(sprom[i]) & 0xFFFF);
591
        }
592
        pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
593
 
594
        return pos + 1;
595
}
596
 
597
static int hex2sprom(u16 *sprom, const char *dump, size_t len)
598
{
599
        char tmp[5] = { 0 };
600
        int cnt = 0;
601
        unsigned long parsed;
602
 
603
        if (len < SSB_SPROMSIZE_BYTES * 2)
604
                return -EINVAL;
605
 
606
        while (cnt < SSB_SPROMSIZE_WORDS) {
607
                memcpy(tmp, dump, 4);
608
                dump += 4;
609
                parsed = simple_strtoul(tmp, NULL, 16);
610
                sprom[cnt++] = swab16((u16)parsed);
611
        }
612
 
613
        return 0;
614
}
615
 
616
static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
617
                                       struct device_attribute *attr,
618
                                       char *buf)
619
{
620
        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
621
        struct ssb_bus *bus;
622
        u16 *sprom;
623
        int err = -ENODEV;
624
        ssize_t count = 0;
625
 
626
        bus = ssb_pci_dev_to_bus(pdev);
627
        if (!bus)
628
                goto out;
629
        err = -ENOMEM;
630
        sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
631
        if (!sprom)
632
                goto out;
633
 
634
        /* Use interruptible locking, as the SPROM write might
635
         * be holding the lock for several seconds. So allow userspace
636
         * to cancel operation. */
637
        err = -ERESTARTSYS;
638
        if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
639
                goto out_kfree;
640
        sprom_do_read(bus, sprom);
641
        mutex_unlock(&bus->pci_sprom_mutex);
642
 
643
        count = sprom2hex(sprom, buf, PAGE_SIZE);
644
        err = 0;
645
 
646
out_kfree:
647
        kfree(sprom);
648
out:
649
        return err ? err : count;
650
}
651
 
652
static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
653
                                        struct device_attribute *attr,
654
                                        const char *buf, size_t count)
655
{
656
        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
657
        struct ssb_bus *bus;
658
        u16 *sprom;
659
        int res = 0, err = -ENODEV;
660
 
661
        bus = ssb_pci_dev_to_bus(pdev);
662
        if (!bus)
663
                goto out;
664
        err = -ENOMEM;
665
        sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
666
        if (!sprom)
667
                goto out;
668
        err = hex2sprom(sprom, buf, count);
669
        if (err) {
670
                err = -EINVAL;
671
                goto out_kfree;
672
        }
673
        err = sprom_check_crc(sprom);
674
        if (err) {
675
                err = -EINVAL;
676
                goto out_kfree;
677
        }
678
 
679
        /* Use interruptible locking, as the SPROM write might
680
         * be holding the lock for several seconds. So allow userspace
681
         * to cancel operation. */
682
        err = -ERESTARTSYS;
683
        if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
684
                goto out_kfree;
685
        err = ssb_devices_freeze(bus);
686
        if (err == -EOPNOTSUPP) {
687
                ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
688
                           "No suspend support. Is CONFIG_PM enabled?\n");
689
                goto out_unlock;
690
        }
691
        if (err) {
692
                ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
693
                goto out_unlock;
694
        }
695
        res = sprom_do_write(bus, sprom);
696
        err = ssb_devices_thaw(bus);
697
        if (err)
698
                ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
699
out_unlock:
700
        mutex_unlock(&bus->pci_sprom_mutex);
701
out_kfree:
702
        kfree(sprom);
703
out:
704
        if (res)
705
                return res;
706
        return err ? err : count;
707
}
708
 
709
static DEVICE_ATTR(ssb_sprom, 0600,
710
                   ssb_pci_attr_sprom_show,
711
                   ssb_pci_attr_sprom_store);
712
 
713
void ssb_pci_exit(struct ssb_bus *bus)
714
{
715
        struct pci_dev *pdev;
716
 
717
        if (bus->bustype != SSB_BUSTYPE_PCI)
718
                return;
719
 
720
        pdev = bus->host_pci;
721
        device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
722
}
723
 
724
int ssb_pci_init(struct ssb_bus *bus)
725
{
726
        struct pci_dev *pdev;
727
        int err;
728
 
729
        if (bus->bustype != SSB_BUSTYPE_PCI)
730
                return 0;
731
 
732
        pdev = bus->host_pci;
733
        mutex_init(&bus->pci_sprom_mutex);
734
        err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
735
        if (err)
736
                goto out;
737
 
738
out:
739
        return err;
740
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.