9e4a121c124e6bcfdb850cc65f33e05ff778b771
[librecmc/librecmc.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 }