]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/ssb/scan.c
Merge branch 'bug-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs...
[net-next-2.6.git] / drivers / ssb / scan.c
CommitLineData
61e115a5
MB
1/*
2 * Sonics Silicon Backplane
3 * Bus scanning
4 *
5 * Copyright (C) 2005-2007 Michael Buesch <mb@bu3sch.de>
6 * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
7 * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
8 * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
9 * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10 * Copyright (C) 2006 Broadcom Corporation.
11 *
12 * Licensed under the GNU/GPL. See COPYING for details.
13 */
14
15#include <linux/ssb/ssb.h>
16#include <linux/ssb/ssb_regs.h>
17#include <linux/pci.h>
18#include <linux/io.h>
19
61e115a5
MB
20#include <pcmcia/cs.h>
21#include <pcmcia/cistpl.h>
22#include <pcmcia/ds.h>
23
24#include "ssb_private.h"
25
26
27const char *ssb_core_name(u16 coreid)
28{
29 switch (coreid) {
30 case SSB_DEV_CHIPCOMMON:
31 return "ChipCommon";
32 case SSB_DEV_ILINE20:
33 return "ILine 20";
34 case SSB_DEV_SDRAM:
35 return "SDRAM";
36 case SSB_DEV_PCI:
37 return "PCI";
38 case SSB_DEV_MIPS:
39 return "MIPS";
40 case SSB_DEV_ETHERNET:
41 return "Fast Ethernet";
42 case SSB_DEV_V90:
43 return "V90";
44 case SSB_DEV_USB11_HOSTDEV:
45 return "USB 1.1 Hostdev";
46 case SSB_DEV_ADSL:
47 return "ADSL";
48 case SSB_DEV_ILINE100:
49 return "ILine 100";
50 case SSB_DEV_IPSEC:
51 return "IPSEC";
52 case SSB_DEV_PCMCIA:
53 return "PCMCIA";
54 case SSB_DEV_INTERNAL_MEM:
55 return "Internal Memory";
56 case SSB_DEV_MEMC_SDRAM:
57 return "MEMC SDRAM";
58 case SSB_DEV_EXTIF:
59 return "EXTIF";
60 case SSB_DEV_80211:
61 return "IEEE 802.11";
62 case SSB_DEV_MIPS_3302:
63 return "MIPS 3302";
64 case SSB_DEV_USB11_HOST:
65 return "USB 1.1 Host";
66 case SSB_DEV_USB11_DEV:
67 return "USB 1.1 Device";
68 case SSB_DEV_USB20_HOST:
69 return "USB 2.0 Host";
70 case SSB_DEV_USB20_DEV:
71 return "USB 2.0 Device";
72 case SSB_DEV_SDIO_HOST:
73 return "SDIO Host";
74 case SSB_DEV_ROBOSWITCH:
75 return "Roboswitch";
76 case SSB_DEV_PARA_ATA:
77 return "PATA";
78 case SSB_DEV_SATA_XORDMA:
79 return "SATA XOR-DMA";
80 case SSB_DEV_ETHERNET_GBIT:
81 return "GBit Ethernet";
82 case SSB_DEV_PCIE:
83 return "PCI-E";
84 case SSB_DEV_MIMO_PHY:
85 return "MIMO PHY";
86 case SSB_DEV_SRAM_CTRLR:
87 return "SRAM Controller";
88 case SSB_DEV_MINI_MACPHY:
89 return "Mini MACPHY";
90 case SSB_DEV_ARM_1176:
91 return "ARM 1176";
92 case SSB_DEV_ARM_7TDMI:
93 return "ARM 7TDMI";
94 }
95 return "UNKNOWN";
96}
97
98static u16 pcidev_to_chipid(struct pci_dev *pci_dev)
99{
100 u16 chipid_fallback = 0;
101
102 switch (pci_dev->device) {
103 case 0x4301:
104 chipid_fallback = 0x4301;
105 break;
106 case 0x4305 ... 0x4307:
107 chipid_fallback = 0x4307;
108 break;
109 case 0x4403:
110 chipid_fallback = 0x4402;
111 break;
112 case 0x4610 ... 0x4615:
113 chipid_fallback = 0x4610;
114 break;
115 case 0x4710 ... 0x4715:
116 chipid_fallback = 0x4710;
117 break;
118 case 0x4320 ... 0x4325:
119 chipid_fallback = 0x4309;
120 break;
121 case PCI_DEVICE_ID_BCM4401:
122 case PCI_DEVICE_ID_BCM4401B0:
123 case PCI_DEVICE_ID_BCM4401B1:
124 chipid_fallback = 0x4401;
125 break;
126 default:
127 ssb_printk(KERN_ERR PFX
128 "PCI-ID not in fallback list\n");
129 }
130
131 return chipid_fallback;
132}
133
134static u8 chipid_to_nrcores(u16 chipid)
135{
136 switch (chipid) {
137 case 0x5365:
138 return 7;
139 case 0x4306:
140 return 6;
141 case 0x4310:
142 return 8;
143 case 0x4307:
144 case 0x4301:
145 return 5;
146 case 0x4401:
147 case 0x4402:
148 return 3;
149 case 0x4710:
150 case 0x4610:
151 case 0x4704:
152 return 9;
153 default:
154 ssb_printk(KERN_ERR PFX
155 "CHIPID not in nrcores fallback list\n");
156 }
157
158 return 1;
159}
160
161static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx,
162 u16 offset)
163{
d8e23522
MF
164 u32 lo, hi;
165
61e115a5
MB
166 switch (bus->bustype) {
167 case SSB_BUSTYPE_SSB:
168 offset += current_coreidx * SSB_CORE_SIZE;
169 break;
170 case SSB_BUSTYPE_PCI:
171 break;
172 case SSB_BUSTYPE_PCMCIA:
173 if (offset >= 0x800) {
174 ssb_pcmcia_switch_segment(bus, 1);
175 offset -= 0x800;
176 } else
177 ssb_pcmcia_switch_segment(bus, 0);
d8e23522
MF
178 lo = readw(bus->mmio + offset);
179 hi = readw(bus->mmio + offset + 2);
180 return lo | (hi << 16);
24ea602e
AH
181 case SSB_BUSTYPE_SDIO:
182 offset += current_coreidx * SSB_CORE_SIZE;
183 return ssb_sdio_scan_read32(bus, offset);
61e115a5
MB
184 }
185 return readl(bus->mmio + offset);
186}
187
188static int scan_switchcore(struct ssb_bus *bus, u8 coreidx)
189{
190 switch (bus->bustype) {
191 case SSB_BUSTYPE_SSB:
192 break;
193 case SSB_BUSTYPE_PCI:
194 return ssb_pci_switch_coreidx(bus, coreidx);
195 case SSB_BUSTYPE_PCMCIA:
196 return ssb_pcmcia_switch_coreidx(bus, coreidx);
24ea602e
AH
197 case SSB_BUSTYPE_SDIO:
198 return ssb_sdio_scan_switch_coreidx(bus, coreidx);
61e115a5
MB
199 }
200 return 0;
201}
202
203void ssb_iounmap(struct ssb_bus *bus)
204{
205 switch (bus->bustype) {
206 case SSB_BUSTYPE_SSB:
207 case SSB_BUSTYPE_PCMCIA:
208 iounmap(bus->mmio);
209 break;
210 case SSB_BUSTYPE_PCI:
211#ifdef CONFIG_SSB_PCIHOST
212 pci_iounmap(bus->host_pci, bus->mmio);
213#else
214 SSB_BUG_ON(1); /* Can't reach this code. */
215#endif
216 break;
24ea602e
AH
217 case SSB_BUSTYPE_SDIO:
218 break;
61e115a5
MB
219 }
220 bus->mmio = NULL;
221 bus->mapped_device = NULL;
222}
223
224static void __iomem *ssb_ioremap(struct ssb_bus *bus,
225 unsigned long baseaddr)
226{
227 void __iomem *mmio = NULL;
228
229 switch (bus->bustype) {
230 case SSB_BUSTYPE_SSB:
231 /* Only map the first core for now. */
232 /* fallthrough... */
233 case SSB_BUSTYPE_PCMCIA:
234 mmio = ioremap(baseaddr, SSB_CORE_SIZE);
235 break;
236 case SSB_BUSTYPE_PCI:
237#ifdef CONFIG_SSB_PCIHOST
238 mmio = pci_iomap(bus->host_pci, 0, ~0UL);
239#else
240 SSB_BUG_ON(1); /* Can't reach this code. */
241#endif
242 break;
24ea602e
AH
243 case SSB_BUSTYPE_SDIO:
244 /* Nothing to ioremap in the SDIO case, just fake it */
245 mmio = (void __iomem *)baseaddr;
246 break;
61e115a5
MB
247 }
248
249 return mmio;
250}
251
252static int we_support_multiple_80211_cores(struct ssb_bus *bus)
253{
254 /* More than one 802.11 core is only supported by special chips.
255 * There are chips with two 802.11 cores, but with dangling
256 * pins on the second core. Be careful and reject them here.
257 */
258
259#ifdef CONFIG_SSB_PCIHOST
260 if (bus->bustype == SSB_BUSTYPE_PCI) {
261 if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM &&
262 bus->host_pci->device == 0x4324)
263 return 1;
264 }
265#endif /* CONFIG_SSB_PCIHOST */
266 return 0;
267}
268
269int ssb_bus_scan(struct ssb_bus *bus,
270 unsigned long baseaddr)
271{
272 int err = -ENOMEM;
273 void __iomem *mmio;
274 u32 idhi, cc, rev, tmp;
275 int dev_i, i;
276 struct ssb_device *dev;
277 int nr_80211_cores = 0;
278
279 mmio = ssb_ioremap(bus, baseaddr);
280 if (!mmio)
281 goto out;
282 bus->mmio = mmio;
283
284 err = scan_switchcore(bus, 0); /* Switch to first core */
285 if (err)
286 goto err_unmap;
287
288 idhi = scan_read32(bus, 0, SSB_IDHIGH);
289 cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
290 rev = (idhi & SSB_IDHIGH_RCLO);
291 rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
292
293 bus->nr_devices = 0;
294 if (cc == SSB_DEV_CHIPCOMMON) {
295 tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID);
296
297 bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
298 bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >>
299 SSB_CHIPCO_REVSHIFT;
300 bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >>
301 SSB_CHIPCO_PACKSHIFT;
302 if (rev >= 4) {
303 bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >>
304 SSB_CHIPCO_NRCORESSHIFT;
305 }
306 tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP);
307 bus->chipco.capabilities = tmp;
308 } else {
309 if (bus->bustype == SSB_BUSTYPE_PCI) {
310 bus->chip_id = pcidev_to_chipid(bus->host_pci);
311 pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
312 &bus->chip_rev);
313 bus->chip_package = 0;
314 } else {
315 bus->chip_id = 0x4710;
316 bus->chip_rev = 0;
317 bus->chip_package = 0;
318 }
319 }
320 if (!bus->nr_devices)
321 bus->nr_devices = chipid_to_nrcores(bus->chip_id);
322 if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
323 ssb_printk(KERN_ERR PFX
324 "More than %d ssb cores found (%d)\n",
325 SSB_MAX_NR_CORES, bus->nr_devices);
326 goto err_unmap;
327 }
328 if (bus->bustype == SSB_BUSTYPE_SSB) {
329 /* Now that we know the number of cores,
330 * remap the whole IO space for all cores.
331 */
332 err = -ENOMEM;
333 iounmap(mmio);
334 mmio = ioremap(baseaddr, SSB_CORE_SIZE * bus->nr_devices);
335 if (!mmio)
336 goto out;
337 bus->mmio = mmio;
338 }
339
340 /* Fetch basic information about each core/device */
341 for (i = 0, dev_i = 0; i < bus->nr_devices; i++) {
342 err = scan_switchcore(bus, i);
343 if (err)
344 goto err_unmap;
345 dev = &(bus->devices[dev_i]);
346
347 idhi = scan_read32(bus, i, SSB_IDHIGH);
348 dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
349 dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
350 dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
351 dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
352 dev->core_index = i;
353 dev->bus = bus;
354 dev->ops = bus->ops;
355
ac2752c1 356 printk(KERN_DEBUG PFX
61e115a5
MB
357 "Core %d found: %s "
358 "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",
359 i, ssb_core_name(dev->id.coreid),
360 dev->id.coreid, dev->id.revision, dev->id.vendor);
361
362 switch (dev->id.coreid) {
363 case SSB_DEV_80211:
364 nr_80211_cores++;
365 if (nr_80211_cores > 1) {
366 if (!we_support_multiple_80211_cores(bus)) {
367 ssb_dprintk(KERN_INFO PFX "Ignoring additional "
368 "802.11 core\n");
369 continue;
370 }
371 }
372 break;
373 case SSB_DEV_EXTIF:
374#ifdef CONFIG_SSB_DRIVER_EXTIF
375 if (bus->extif.dev) {
376 ssb_printk(KERN_WARNING PFX
377 "WARNING: Multiple EXTIFs found\n");
378 break;
379 }
380 bus->extif.dev = dev;
381#endif /* CONFIG_SSB_DRIVER_EXTIF */
382 break;
383 case SSB_DEV_CHIPCOMMON:
384 if (bus->chipco.dev) {
385 ssb_printk(KERN_WARNING PFX
386 "WARNING: Multiple ChipCommon found\n");
387 break;
388 }
389 bus->chipco.dev = dev;
390 break;
391 case SSB_DEV_MIPS:
392 case SSB_DEV_MIPS_3302:
393#ifdef CONFIG_SSB_DRIVER_MIPS
394 if (bus->mipscore.dev) {
395 ssb_printk(KERN_WARNING PFX
396 "WARNING: Multiple MIPS cores found\n");
397 break;
398 }
399 bus->mipscore.dev = dev;
400#endif /* CONFIG_SSB_DRIVER_MIPS */
401 break;
402 case SSB_DEV_PCI:
403 case SSB_DEV_PCIE:
404#ifdef CONFIG_SSB_DRIVER_PCICORE
87c4ac84
MB
405 if (bus->bustype == SSB_BUSTYPE_PCI) {
406 /* Ignore PCI cores on PCI-E cards.
407 * Ignore PCI-E cores on PCI cards. */
408 if (dev->id.coreid == SSB_DEV_PCI) {
409 if (bus->host_pci->is_pcie)
410 continue;
411 } else {
412 if (!bus->host_pci->is_pcie)
413 continue;
414 }
415 }
61e115a5
MB
416 if (bus->pcicore.dev) {
417 ssb_printk(KERN_WARNING PFX
418 "WARNING: Multiple PCI(E) cores found\n");
419 break;
420 }
421 bus->pcicore.dev = dev;
422#endif /* CONFIG_SSB_DRIVER_PCICORE */
423 break;
424 default:
425 break;
426 }
427
428 dev_i++;
429 }
430 bus->nr_devices = dev_i;
431
432 err = 0;
433out:
434 return err;
435err_unmap:
436 ssb_iounmap(bus);
437 goto out;
438}