9e4a121c124e6bcfdb850cc65f33e05ff778b771
[openwrt/svn-archive/archive.git] / target / linux / brcm47xx-2.6 / files / drivers / ssb / scan.c
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 <asm/io.h>
19
20 #include "ssb_private.h"
21
22
23 const char * ssb_core_name(u16 coreid)
24 {
25 switch (coreid) {
26 case SSB_DEV_CHIPCOMMON:
27 return "ChipCommon";
28 case SSB_DEV_ILINE20:
29 return "ILine 20";
30 case SSB_DEV_SDRAM:
31 return "SDRAM";
32 case SSB_DEV_PCI:
33 return "PCI";
34 case SSB_DEV_MIPS:
35 return "MIPS";
36 case SSB_DEV_ETHERNET:
37 return "Fast Ethernet";
38 case SSB_DEV_V90:
39 return "V90";
40 case SSB_DEV_USB11_HOSTDEV:
41 return "USB 1.1 Hostdev";
42 case SSB_DEV_ADSL:
43 return "ADSL";
44 case SSB_DEV_ILINE100:
45 return "ILine 100";
46 case SSB_DEV_IPSEC:
47 return "IPSEC";
48 case SSB_DEV_PCMCIA:
49 return "PCMCIA";
50 case SSB_DEV_INTERNAL_MEM:
51 return "Internal Memory";
52 case SSB_DEV_MEMC_SDRAM:
53 return "MEMC SDRAM";
54 case SSB_DEV_EXTIF:
55 return "EXTIF";
56 case SSB_DEV_80211:
57 return "IEEE 802.11";
58 case SSB_DEV_MIPS_3302:
59 return "MIPS 3302";
60 case SSB_DEV_USB11_HOST:
61 return "USB 1.1 Host";
62 case SSB_DEV_USB11_DEV:
63 return "USB 1.1 Device";
64 case SSB_DEV_USB20_HOST:
65 return "USB 2.0 Host";
66 case SSB_DEV_USB20_DEV:
67 return "USB 2.0 Device";
68 case SSB_DEV_SDIO_HOST:
69 return "SDIO Host";
70 case SSB_DEV_ROBOSWITCH:
71 return "Roboswitch";
72 case SSB_DEV_PARA_ATA:
73 return "PATA";
74 case SSB_DEV_SATA_XORDMA:
75 return "SATA XOR-DMA";
76 case SSB_DEV_ETHERNET_GBIT:
77 return "GBit Ethernet";
78 case SSB_DEV_PCIE:
79 return "PCI-E";
80 case SSB_DEV_MIMO_PHY:
81 return "MIMO PHY";
82 case SSB_DEV_SRAM_CTRLR:
83 return "SRAM Controller";
84 case SSB_DEV_MINI_MACPHY:
85 return "Mini MACPHY";
86 case SSB_DEV_ARM_1176:
87 return "ARM 1176";
88 case SSB_DEV_ARM_7TDMI:
89 return "ARM 7TDMI";
90 }
91 return "UNKNOWN";
92 }
93
94 static u16 pcidev_to_chipid(struct pci_dev *pci_dev)
95 {
96 u16 chipid_fallback = 0;
97
98 switch (pci_dev->device) {
99 case 0x4301:
100 chipid_fallback = 0x4301;
101 break;
102 case 0x4305 ... 0x4307:
103 chipid_fallback = 0x4307;
104 break;
105 case 0x4403:
106 chipid_fallback = 0x4402;
107 break;
108 case 0x4610 ... 0x4615:
109 chipid_fallback = 0x4610;
110 break;
111 case 0x4710 ... 0x4715:
112 chipid_fallback = 0x4710;
113 break;
114 case 0x4320 ... 0x4325:
115 chipid_fallback = 0x4309;
116 break;
117 case PCI_DEVICE_ID_BCM4401:
118 case PCI_DEVICE_ID_BCM4401B0:
119 case PCI_DEVICE_ID_BCM4401B1:
120 chipid_fallback = 0x4401;
121 break;
122 default:
123 ssb_printk(KERN_ERR PFX
124 "PCI-ID not in fallback list\n");
125 }
126
127 return chipid_fallback;
128 }
129
130 static u8 chipid_to_nrcores(u16 chipid)
131 {
132 switch (chipid) {
133 case 0x5365:
134 return 7;
135 case 0x4306:
136 return 6;
137 case 0x4310:
138 return 8;
139 case 0x4307:
140 case 0x4301:
141 return 5;
142 case 0x4401:
143 case 0x4402:
144 return 3;
145 case 0x4710:
146 case 0x4610:
147 case 0x4704:
148 return 9;
149 default:
150 ssb_printk(KERN_ERR PFX
151 "CHIPID not in nrcores fallback list\n");
152 }
153
154 return 1;
155 }
156
157 static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx,
158 u16 offset)
159 {
160 switch (bus->bustype) {
161 case SSB_BUSTYPE_SSB:
162 offset += current_coreidx * SSB_CORE_SIZE;
163 break;
164 case SSB_BUSTYPE_PCI:
165 break;
166 case SSB_BUSTYPE_PCMCIA:
167 if (offset >= 0x800) {
168 ssb_pcmcia_switch_segment(bus, 1);
169 offset -= 0x800;
170 } else
171 ssb_pcmcia_switch_segment(bus, 0);
172 break;
173 }
174 return readl(bus->mmio + offset);
175 }
176
177 static int scan_switchcore(struct ssb_bus *bus, u8 coreidx)
178 {
179 switch (bus->bustype) {
180 case SSB_BUSTYPE_SSB:
181 break;
182 case SSB_BUSTYPE_PCI:
183 return ssb_pci_switch_coreidx(bus, coreidx);
184 case SSB_BUSTYPE_PCMCIA:
185 return ssb_pcmcia_switch_coreidx(bus, coreidx);
186 }
187 return 0;
188 }
189
190 void ssb_iounmap(struct ssb_bus *bus)
191 {
192 switch (bus->bustype) {
193 case SSB_BUSTYPE_SSB:
194 case SSB_BUSTYPE_PCMCIA:
195 iounmap(bus->mmio);
196 break;
197 case SSB_BUSTYPE_PCI:
198 pci_iounmap(bus->host_pci, bus->mmio);
199 break;
200 }
201 bus->mmio = NULL;
202 bus->mapped_device = NULL;
203 }
204
205 static void __iomem * ssb_ioremap(struct ssb_bus *bus,
206 unsigned long baseaddr)
207 {
208 void __iomem *mmio = NULL;
209
210 switch (bus->bustype) {
211 case SSB_BUSTYPE_SSB:
212 /* Only map the first core for now. */
213 /* fallthrough... */
214 case SSB_BUSTYPE_PCMCIA:
215 mmio = ioremap(baseaddr, SSB_CORE_SIZE);
216 break;
217 case SSB_BUSTYPE_PCI:
218 mmio = pci_iomap(bus->host_pci, 0, ~0UL);
219 break;
220 }
221
222 return mmio;
223 }
224
225 int ssb_bus_scan(struct ssb_bus *bus,
226 unsigned long baseaddr)
227 {
228 int err = -ENOMEM;
229 void __iomem *mmio;
230 u32 idhi, cc, rev, tmp;
231 int i;
232 struct ssb_device *dev;
233
234 mmio = ssb_ioremap(bus, baseaddr);
235 if (!mmio)
236 goto out;
237 bus->mmio = mmio;
238
239 err = scan_switchcore(bus, 0); /* Switch to first core */
240 if (err)
241 goto err_unmap;
242
243 idhi = scan_read32(bus, 0, SSB_IDHIGH);
244 cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
245 rev = (idhi & SSB_IDHIGH_RCLO);
246 rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
247
248 bus->nr_devices = 0;
249 if (cc == SSB_DEV_CHIPCOMMON) {
250 tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID);
251
252 bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
253 bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >>
254 SSB_CHIPCO_REVSHIFT;
255 bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >>
256 SSB_CHIPCO_PACKSHIFT;
257 if (rev >= 4) {
258 bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >>
259 SSB_CHIPCO_NRCORESSHIFT;
260 }
261 tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP);
262 bus->chipco.capabilities = tmp;
263 } else {
264 if (bus->bustype == SSB_BUSTYPE_PCI) {
265 bus->chip_id = pcidev_to_chipid(bus->host_pci);
266 pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
267 &bus->chip_rev);
268 bus->chip_package = 0;
269 } else {
270 bus->chip_id = 0x4710;
271 bus->chip_rev = 0;
272 bus->chip_package = 0;
273 }
274 }
275 if (!bus->nr_devices)
276 bus->nr_devices = chipid_to_nrcores(bus->chip_id);
277 if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
278 ssb_printk(KERN_ERR PFX
279 "More than %d ssb cores found (%d)\n",
280 SSB_MAX_NR_CORES, bus->nr_devices);
281 goto err_unmap;
282 }
283 if (bus->bustype == SSB_BUSTYPE_SSB) {
284 /* Now that we know the number of cores,
285 * remap the whole IO space for all cores.
286 */
287 err = -ENOMEM;
288 iounmap(mmio);
289 mmio = ioremap(baseaddr, SSB_CORE_SIZE * bus->nr_devices);
290 if (!mmio)
291 goto out;
292 bus->mmio = mmio;
293 }
294
295 /* Fetch basic information about each core/device */
296 for (i = 0; i < bus->nr_devices; i++) {
297 err = scan_switchcore(bus, i);
298 if (err)
299 goto err_unmap;
300 dev = &(bus->devices[i]);
301
302 idhi = scan_read32(bus, i, SSB_IDHIGH);
303 dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
304 dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
305 dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
306 dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
307 dev->core_index = i;
308 dev->bus = bus;
309 if ((dev->bus->bustype == SSB_BUSTYPE_PCI) && (bus->host_pci))
310 dev->irq = bus->host_pci->irq;
311
312 ssb_dprintk(KERN_INFO PFX
313 "Core %d found: %s "
314 "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",
315 i, ssb_core_name(dev->id.coreid),
316 dev->id.coreid, dev->id.revision, dev->id.vendor);
317
318 dev->dev.bus = &ssb_bustype;
319 snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
320 "ssb%02x:%02x", bus->busnumber, i);
321
322 switch (dev->id.coreid) {
323 case SSB_DEV_EXTIF:
324 #ifdef CONFIG_BCM947XX
325 if (bus->extif.dev) {
326 ssb_printk(KERN_WARNING PFX
327 "WARNING: Multiple EXTIFs found\n");
328 break;
329 }
330 bus->extif.dev = dev;
331 #endif /* CONFIG_SSB_DRIVER_EXTIF */
332 break;
333 case SSB_DEV_CHIPCOMMON:
334 if (bus->chipco.dev) {
335 ssb_printk(KERN_WARNING PFX
336 "WARNING: Multiple ChipCommon found\n");
337 break;
338 }
339 bus->chipco.dev = dev;
340 break;
341 case SSB_DEV_MIPS:
342 case SSB_DEV_MIPS_3302:
343 #ifdef CONFIG_BCM947XX
344 if (bus->mipscore.dev) {
345 ssb_printk(KERN_WARNING PFX
346 "WARNING: Multiple MIPS cores found\n");
347 break;
348 }
349 bus->mipscore.dev = dev;
350 #endif /* CONFIG_BCM947XX */
351 break;
352 case SSB_DEV_PCI:
353 case SSB_DEV_PCIE:
354 #ifdef CONFIG_SSB_DRIVER_PCICORE
355 if (bus->pcicore.dev) {
356 ssb_printk(KERN_WARNING PFX
357 "WARNING: Multiple PCI(E) cores found\n");
358 break;
359 }
360 bus->pcicore.dev = dev;
361 #endif /* CONFIG_SSB_DRIVER_PCICORE */
362 break;
363 default:
364 break;
365 }
366 }
367 err = 0;
368 out:
369 return err;
370 err_unmap:
371 ssb_iounmap(bus);
372 goto out;
373 }