161e115a5SMichael Buesch /* 261e115a5SMichael Buesch * Sonics Silicon Backplane 361e115a5SMichael Buesch * Bus scanning 461e115a5SMichael Buesch * 5eb032b98SMichael Büsch * Copyright (C) 2005-2007 Michael Buesch <m@bues.ch> 661e115a5SMichael Buesch * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de> 761e115a5SMichael Buesch * Copyright (C) 2005 Stefano Brivio <st3@riseup.net> 861e115a5SMichael Buesch * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org> 961e115a5SMichael Buesch * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> 1061e115a5SMichael Buesch * Copyright (C) 2006 Broadcom Corporation. 1161e115a5SMichael Buesch * 1261e115a5SMichael Buesch * Licensed under the GNU/GPL. See COPYING for details. 1361e115a5SMichael Buesch */ 1461e115a5SMichael Buesch 1561e115a5SMichael Buesch #include <linux/ssb/ssb.h> 1661e115a5SMichael Buesch #include <linux/ssb/ssb_regs.h> 1761e115a5SMichael Buesch #include <linux/pci.h> 1861e115a5SMichael Buesch #include <linux/io.h> 1961e115a5SMichael Buesch 2061e115a5SMichael Buesch #include <pcmcia/cistpl.h> 2161e115a5SMichael Buesch #include <pcmcia/ds.h> 2261e115a5SMichael Buesch 2361e115a5SMichael Buesch #include "ssb_private.h" 2461e115a5SMichael Buesch 2561e115a5SMichael Buesch 2661e115a5SMichael Buesch const char *ssb_core_name(u16 coreid) 2761e115a5SMichael Buesch { 2861e115a5SMichael Buesch switch (coreid) { 2961e115a5SMichael Buesch case SSB_DEV_CHIPCOMMON: 3061e115a5SMichael Buesch return "ChipCommon"; 3161e115a5SMichael Buesch case SSB_DEV_ILINE20: 3261e115a5SMichael Buesch return "ILine 20"; 3361e115a5SMichael Buesch case SSB_DEV_SDRAM: 3461e115a5SMichael Buesch return "SDRAM"; 3561e115a5SMichael Buesch case SSB_DEV_PCI: 3661e115a5SMichael Buesch return "PCI"; 3761e115a5SMichael Buesch case SSB_DEV_MIPS: 3861e115a5SMichael Buesch return "MIPS"; 3961e115a5SMichael Buesch case SSB_DEV_ETHERNET: 4061e115a5SMichael Buesch return "Fast Ethernet"; 4161e115a5SMichael Buesch case SSB_DEV_V90: 4261e115a5SMichael Buesch return "V90"; 4361e115a5SMichael Buesch case SSB_DEV_USB11_HOSTDEV: 4461e115a5SMichael Buesch return "USB 1.1 Hostdev"; 4561e115a5SMichael Buesch case SSB_DEV_ADSL: 4661e115a5SMichael Buesch return "ADSL"; 4761e115a5SMichael Buesch case SSB_DEV_ILINE100: 4861e115a5SMichael Buesch return "ILine 100"; 4961e115a5SMichael Buesch case SSB_DEV_IPSEC: 5061e115a5SMichael Buesch return "IPSEC"; 5161e115a5SMichael Buesch case SSB_DEV_PCMCIA: 5261e115a5SMichael Buesch return "PCMCIA"; 5361e115a5SMichael Buesch case SSB_DEV_INTERNAL_MEM: 5461e115a5SMichael Buesch return "Internal Memory"; 5561e115a5SMichael Buesch case SSB_DEV_MEMC_SDRAM: 5661e115a5SMichael Buesch return "MEMC SDRAM"; 5761e115a5SMichael Buesch case SSB_DEV_EXTIF: 5861e115a5SMichael Buesch return "EXTIF"; 5961e115a5SMichael Buesch case SSB_DEV_80211: 6061e115a5SMichael Buesch return "IEEE 802.11"; 6161e115a5SMichael Buesch case SSB_DEV_MIPS_3302: 6261e115a5SMichael Buesch return "MIPS 3302"; 6361e115a5SMichael Buesch case SSB_DEV_USB11_HOST: 6461e115a5SMichael Buesch return "USB 1.1 Host"; 6561e115a5SMichael Buesch case SSB_DEV_USB11_DEV: 6661e115a5SMichael Buesch return "USB 1.1 Device"; 6761e115a5SMichael Buesch case SSB_DEV_USB20_HOST: 6861e115a5SMichael Buesch return "USB 2.0 Host"; 6961e115a5SMichael Buesch case SSB_DEV_USB20_DEV: 7061e115a5SMichael Buesch return "USB 2.0 Device"; 7161e115a5SMichael Buesch case SSB_DEV_SDIO_HOST: 7261e115a5SMichael Buesch return "SDIO Host"; 7361e115a5SMichael Buesch case SSB_DEV_ROBOSWITCH: 7461e115a5SMichael Buesch return "Roboswitch"; 7561e115a5SMichael Buesch case SSB_DEV_PARA_ATA: 7661e115a5SMichael Buesch return "PATA"; 7761e115a5SMichael Buesch case SSB_DEV_SATA_XORDMA: 7861e115a5SMichael Buesch return "SATA XOR-DMA"; 7961e115a5SMichael Buesch case SSB_DEV_ETHERNET_GBIT: 8061e115a5SMichael Buesch return "GBit Ethernet"; 8161e115a5SMichael Buesch case SSB_DEV_PCIE: 8261e115a5SMichael Buesch return "PCI-E"; 8361e115a5SMichael Buesch case SSB_DEV_MIMO_PHY: 8461e115a5SMichael Buesch return "MIMO PHY"; 8561e115a5SMichael Buesch case SSB_DEV_SRAM_CTRLR: 8661e115a5SMichael Buesch return "SRAM Controller"; 8761e115a5SMichael Buesch case SSB_DEV_MINI_MACPHY: 8861e115a5SMichael Buesch return "Mini MACPHY"; 8961e115a5SMichael Buesch case SSB_DEV_ARM_1176: 9061e115a5SMichael Buesch return "ARM 1176"; 9161e115a5SMichael Buesch case SSB_DEV_ARM_7TDMI: 9261e115a5SMichael Buesch return "ARM 7TDMI"; 93ccaf8c32SHauke Mehrtens case SSB_DEV_ARM_CM3: 94ccaf8c32SHauke Mehrtens return "ARM Cortex M3"; 9561e115a5SMichael Buesch } 9661e115a5SMichael Buesch return "UNKNOWN"; 9761e115a5SMichael Buesch } 9861e115a5SMichael Buesch 9961e115a5SMichael Buesch static u16 pcidev_to_chipid(struct pci_dev *pci_dev) 10061e115a5SMichael Buesch { 10161e115a5SMichael Buesch u16 chipid_fallback = 0; 10261e115a5SMichael Buesch 10361e115a5SMichael Buesch switch (pci_dev->device) { 10461e115a5SMichael Buesch case 0x4301: 10561e115a5SMichael Buesch chipid_fallback = 0x4301; 10661e115a5SMichael Buesch break; 10761e115a5SMichael Buesch case 0x4305 ... 0x4307: 10861e115a5SMichael Buesch chipid_fallback = 0x4307; 10961e115a5SMichael Buesch break; 11061e115a5SMichael Buesch case 0x4403: 11161e115a5SMichael Buesch chipid_fallback = 0x4402; 11261e115a5SMichael Buesch break; 11361e115a5SMichael Buesch case 0x4610 ... 0x4615: 11461e115a5SMichael Buesch chipid_fallback = 0x4610; 11561e115a5SMichael Buesch break; 11661e115a5SMichael Buesch case 0x4710 ... 0x4715: 11761e115a5SMichael Buesch chipid_fallback = 0x4710; 11861e115a5SMichael Buesch break; 11961e115a5SMichael Buesch case 0x4320 ... 0x4325: 12061e115a5SMichael Buesch chipid_fallback = 0x4309; 12161e115a5SMichael Buesch break; 12261e115a5SMichael Buesch case PCI_DEVICE_ID_BCM4401: 12361e115a5SMichael Buesch case PCI_DEVICE_ID_BCM4401B0: 12461e115a5SMichael Buesch case PCI_DEVICE_ID_BCM4401B1: 12561e115a5SMichael Buesch chipid_fallback = 0x4401; 12661e115a5SMichael Buesch break; 12761e115a5SMichael Buesch default: 12861e115a5SMichael Buesch ssb_printk(KERN_ERR PFX 12961e115a5SMichael Buesch "PCI-ID not in fallback list\n"); 13061e115a5SMichael Buesch } 13161e115a5SMichael Buesch 13261e115a5SMichael Buesch return chipid_fallback; 13361e115a5SMichael Buesch } 13461e115a5SMichael Buesch 13561e115a5SMichael Buesch static u8 chipid_to_nrcores(u16 chipid) 13661e115a5SMichael Buesch { 13761e115a5SMichael Buesch switch (chipid) { 13861e115a5SMichael Buesch case 0x5365: 13961e115a5SMichael Buesch return 7; 14061e115a5SMichael Buesch case 0x4306: 14161e115a5SMichael Buesch return 6; 14261e115a5SMichael Buesch case 0x4310: 14361e115a5SMichael Buesch return 8; 14461e115a5SMichael Buesch case 0x4307: 14561e115a5SMichael Buesch case 0x4301: 14661e115a5SMichael Buesch return 5; 14761e115a5SMichael Buesch case 0x4401: 14861e115a5SMichael Buesch case 0x4402: 14961e115a5SMichael Buesch return 3; 15061e115a5SMichael Buesch case 0x4710: 15161e115a5SMichael Buesch case 0x4610: 15261e115a5SMichael Buesch case 0x4704: 15361e115a5SMichael Buesch return 9; 15461e115a5SMichael Buesch default: 15561e115a5SMichael Buesch ssb_printk(KERN_ERR PFX 15661e115a5SMichael Buesch "CHIPID not in nrcores fallback list\n"); 15761e115a5SMichael Buesch } 15861e115a5SMichael Buesch 15961e115a5SMichael Buesch return 1; 16061e115a5SMichael Buesch } 16161e115a5SMichael Buesch 16261e115a5SMichael Buesch static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, 16361e115a5SMichael Buesch u16 offset) 16461e115a5SMichael Buesch { 165d8e23522SMartin Fuzzey u32 lo, hi; 166d8e23522SMartin Fuzzey 16761e115a5SMichael Buesch switch (bus->bustype) { 16861e115a5SMichael Buesch case SSB_BUSTYPE_SSB: 16961e115a5SMichael Buesch offset += current_coreidx * SSB_CORE_SIZE; 17061e115a5SMichael Buesch break; 17161e115a5SMichael Buesch case SSB_BUSTYPE_PCI: 17261e115a5SMichael Buesch break; 17361e115a5SMichael Buesch case SSB_BUSTYPE_PCMCIA: 17461e115a5SMichael Buesch if (offset >= 0x800) { 17561e115a5SMichael Buesch ssb_pcmcia_switch_segment(bus, 1); 17661e115a5SMichael Buesch offset -= 0x800; 17761e115a5SMichael Buesch } else 17861e115a5SMichael Buesch ssb_pcmcia_switch_segment(bus, 0); 179d8e23522SMartin Fuzzey lo = readw(bus->mmio + offset); 180d8e23522SMartin Fuzzey hi = readw(bus->mmio + offset + 2); 181d8e23522SMartin Fuzzey return lo | (hi << 16); 18224ea602eSAlbert Herranz case SSB_BUSTYPE_SDIO: 18324ea602eSAlbert Herranz offset += current_coreidx * SSB_CORE_SIZE; 18424ea602eSAlbert Herranz return ssb_sdio_scan_read32(bus, offset); 18561e115a5SMichael Buesch } 18661e115a5SMichael Buesch return readl(bus->mmio + offset); 18761e115a5SMichael Buesch } 18861e115a5SMichael Buesch 18961e115a5SMichael Buesch static int scan_switchcore(struct ssb_bus *bus, u8 coreidx) 19061e115a5SMichael Buesch { 19161e115a5SMichael Buesch switch (bus->bustype) { 19261e115a5SMichael Buesch case SSB_BUSTYPE_SSB: 19361e115a5SMichael Buesch break; 19461e115a5SMichael Buesch case SSB_BUSTYPE_PCI: 19561e115a5SMichael Buesch return ssb_pci_switch_coreidx(bus, coreidx); 19661e115a5SMichael Buesch case SSB_BUSTYPE_PCMCIA: 19761e115a5SMichael Buesch return ssb_pcmcia_switch_coreidx(bus, coreidx); 19824ea602eSAlbert Herranz case SSB_BUSTYPE_SDIO: 19924ea602eSAlbert Herranz return ssb_sdio_scan_switch_coreidx(bus, coreidx); 20061e115a5SMichael Buesch } 20161e115a5SMichael Buesch return 0; 20261e115a5SMichael Buesch } 20361e115a5SMichael Buesch 20461e115a5SMichael Buesch void ssb_iounmap(struct ssb_bus *bus) 20561e115a5SMichael Buesch { 20661e115a5SMichael Buesch switch (bus->bustype) { 20761e115a5SMichael Buesch case SSB_BUSTYPE_SSB: 20861e115a5SMichael Buesch case SSB_BUSTYPE_PCMCIA: 20961e115a5SMichael Buesch iounmap(bus->mmio); 21061e115a5SMichael Buesch break; 21161e115a5SMichael Buesch case SSB_BUSTYPE_PCI: 21261e115a5SMichael Buesch #ifdef CONFIG_SSB_PCIHOST 21361e115a5SMichael Buesch pci_iounmap(bus->host_pci, bus->mmio); 21461e115a5SMichael Buesch #else 21561e115a5SMichael Buesch SSB_BUG_ON(1); /* Can't reach this code. */ 21661e115a5SMichael Buesch #endif 21761e115a5SMichael Buesch break; 21824ea602eSAlbert Herranz case SSB_BUSTYPE_SDIO: 21924ea602eSAlbert Herranz break; 22061e115a5SMichael Buesch } 22161e115a5SMichael Buesch bus->mmio = NULL; 22261e115a5SMichael Buesch bus->mapped_device = NULL; 22361e115a5SMichael Buesch } 22461e115a5SMichael Buesch 22561e115a5SMichael Buesch static void __iomem *ssb_ioremap(struct ssb_bus *bus, 22661e115a5SMichael Buesch unsigned long baseaddr) 22761e115a5SMichael Buesch { 22861e115a5SMichael Buesch void __iomem *mmio = NULL; 22961e115a5SMichael Buesch 23061e115a5SMichael Buesch switch (bus->bustype) { 23161e115a5SMichael Buesch case SSB_BUSTYPE_SSB: 23261e115a5SMichael Buesch /* Only map the first core for now. */ 23361e115a5SMichael Buesch /* fallthrough... */ 23461e115a5SMichael Buesch case SSB_BUSTYPE_PCMCIA: 23561e115a5SMichael Buesch mmio = ioremap(baseaddr, SSB_CORE_SIZE); 23661e115a5SMichael Buesch break; 23761e115a5SMichael Buesch case SSB_BUSTYPE_PCI: 23861e115a5SMichael Buesch #ifdef CONFIG_SSB_PCIHOST 23961e115a5SMichael Buesch mmio = pci_iomap(bus->host_pci, 0, ~0UL); 24061e115a5SMichael Buesch #else 24161e115a5SMichael Buesch SSB_BUG_ON(1); /* Can't reach this code. */ 24261e115a5SMichael Buesch #endif 24361e115a5SMichael Buesch break; 24424ea602eSAlbert Herranz case SSB_BUSTYPE_SDIO: 24524ea602eSAlbert Herranz /* Nothing to ioremap in the SDIO case, just fake it */ 24624ea602eSAlbert Herranz mmio = (void __iomem *)baseaddr; 24724ea602eSAlbert Herranz break; 24861e115a5SMichael Buesch } 24961e115a5SMichael Buesch 25061e115a5SMichael Buesch return mmio; 25161e115a5SMichael Buesch } 25261e115a5SMichael Buesch 25361e115a5SMichael Buesch static int we_support_multiple_80211_cores(struct ssb_bus *bus) 25461e115a5SMichael Buesch { 25561e115a5SMichael Buesch /* More than one 802.11 core is only supported by special chips. 25661e115a5SMichael Buesch * There are chips with two 802.11 cores, but with dangling 25761e115a5SMichael Buesch * pins on the second core. Be careful and reject them here. 25861e115a5SMichael Buesch */ 25961e115a5SMichael Buesch 26061e115a5SMichael Buesch #ifdef CONFIG_SSB_PCIHOST 26161e115a5SMichael Buesch if (bus->bustype == SSB_BUSTYPE_PCI) { 26261e115a5SMichael Buesch if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && 2639fcce61cSRafał Miłecki ((bus->host_pci->device == 0x4313) || 2649fcce61cSRafał Miłecki (bus->host_pci->device == 0x431A) || 2659fcce61cSRafał Miłecki (bus->host_pci->device == 0x4321) || 2669fcce61cSRafał Miłecki (bus->host_pci->device == 0x4324))) 26761e115a5SMichael Buesch return 1; 26861e115a5SMichael Buesch } 26961e115a5SMichael Buesch #endif /* CONFIG_SSB_PCIHOST */ 27061e115a5SMichael Buesch return 0; 27161e115a5SMichael Buesch } 27261e115a5SMichael Buesch 27361e115a5SMichael Buesch int ssb_bus_scan(struct ssb_bus *bus, 27461e115a5SMichael Buesch unsigned long baseaddr) 27561e115a5SMichael Buesch { 27661e115a5SMichael Buesch int err = -ENOMEM; 27761e115a5SMichael Buesch void __iomem *mmio; 27861e115a5SMichael Buesch u32 idhi, cc, rev, tmp; 27961e115a5SMichael Buesch int dev_i, i; 28061e115a5SMichael Buesch struct ssb_device *dev; 28161e115a5SMichael Buesch int nr_80211_cores = 0; 28261e115a5SMichael Buesch 28361e115a5SMichael Buesch mmio = ssb_ioremap(bus, baseaddr); 28461e115a5SMichael Buesch if (!mmio) 28561e115a5SMichael Buesch goto out; 28661e115a5SMichael Buesch bus->mmio = mmio; 28761e115a5SMichael Buesch 28861e115a5SMichael Buesch err = scan_switchcore(bus, 0); /* Switch to first core */ 28961e115a5SMichael Buesch if (err) 29061e115a5SMichael Buesch goto err_unmap; 29161e115a5SMichael Buesch 29261e115a5SMichael Buesch idhi = scan_read32(bus, 0, SSB_IDHIGH); 29361e115a5SMichael Buesch cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT; 29461e115a5SMichael Buesch rev = (idhi & SSB_IDHIGH_RCLO); 29561e115a5SMichael Buesch rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT; 29661e115a5SMichael Buesch 29761e115a5SMichael Buesch bus->nr_devices = 0; 29861e115a5SMichael Buesch if (cc == SSB_DEV_CHIPCOMMON) { 29961e115a5SMichael Buesch tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID); 30061e115a5SMichael Buesch 30161e115a5SMichael Buesch bus->chip_id = (tmp & SSB_CHIPCO_IDMASK); 30261e115a5SMichael Buesch bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >> 30361e115a5SMichael Buesch SSB_CHIPCO_REVSHIFT; 30461e115a5SMichael Buesch bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >> 30561e115a5SMichael Buesch SSB_CHIPCO_PACKSHIFT; 30661e115a5SMichael Buesch if (rev >= 4) { 30761e115a5SMichael Buesch bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >> 30861e115a5SMichael Buesch SSB_CHIPCO_NRCORESSHIFT; 30961e115a5SMichael Buesch } 31061e115a5SMichael Buesch tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP); 31161e115a5SMichael Buesch bus->chipco.capabilities = tmp; 31261e115a5SMichael Buesch } else { 31361e115a5SMichael Buesch if (bus->bustype == SSB_BUSTYPE_PCI) { 31461e115a5SMichael Buesch bus->chip_id = pcidev_to_chipid(bus->host_pci); 315ce2dd3c2SSergei Shtylyov bus->chip_rev = bus->host_pci->revision; 31661e115a5SMichael Buesch bus->chip_package = 0; 31761e115a5SMichael Buesch } else { 31861e115a5SMichael Buesch bus->chip_id = 0x4710; 31961e115a5SMichael Buesch bus->chip_rev = 0; 32061e115a5SMichael Buesch bus->chip_package = 0; 32161e115a5SMichael Buesch } 32261e115a5SMichael Buesch } 323bedb2a18SHauke Mehrtens ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and " 324bedb2a18SHauke Mehrtens "package 0x%02X\n", bus->chip_id, bus->chip_rev, 325bedb2a18SHauke Mehrtens bus->chip_package); 32661e115a5SMichael Buesch if (!bus->nr_devices) 32761e115a5SMichael Buesch bus->nr_devices = chipid_to_nrcores(bus->chip_id); 32861e115a5SMichael Buesch if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { 32961e115a5SMichael Buesch ssb_printk(KERN_ERR PFX 33061e115a5SMichael Buesch "More than %d ssb cores found (%d)\n", 33161e115a5SMichael Buesch SSB_MAX_NR_CORES, bus->nr_devices); 33261e115a5SMichael Buesch goto err_unmap; 33361e115a5SMichael Buesch } 33461e115a5SMichael Buesch if (bus->bustype == SSB_BUSTYPE_SSB) { 33561e115a5SMichael Buesch /* Now that we know the number of cores, 33661e115a5SMichael Buesch * remap the whole IO space for all cores. 33761e115a5SMichael Buesch */ 33861e115a5SMichael Buesch err = -ENOMEM; 33961e115a5SMichael Buesch iounmap(mmio); 34061e115a5SMichael Buesch mmio = ioremap(baseaddr, SSB_CORE_SIZE * bus->nr_devices); 34161e115a5SMichael Buesch if (!mmio) 34261e115a5SMichael Buesch goto out; 34361e115a5SMichael Buesch bus->mmio = mmio; 34461e115a5SMichael Buesch } 34561e115a5SMichael Buesch 34661e115a5SMichael Buesch /* Fetch basic information about each core/device */ 34761e115a5SMichael Buesch for (i = 0, dev_i = 0; i < bus->nr_devices; i++) { 34861e115a5SMichael Buesch err = scan_switchcore(bus, i); 34961e115a5SMichael Buesch if (err) 35061e115a5SMichael Buesch goto err_unmap; 35161e115a5SMichael Buesch dev = &(bus->devices[dev_i]); 35261e115a5SMichael Buesch 35361e115a5SMichael Buesch idhi = scan_read32(bus, i, SSB_IDHIGH); 35461e115a5SMichael Buesch dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT; 35561e115a5SMichael Buesch dev->id.revision = (idhi & SSB_IDHIGH_RCLO); 35661e115a5SMichael Buesch dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT; 35761e115a5SMichael Buesch dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT; 35861e115a5SMichael Buesch dev->core_index = i; 35961e115a5SMichael Buesch dev->bus = bus; 36061e115a5SMichael Buesch dev->ops = bus->ops; 36161e115a5SMichael Buesch 362ac2752c1SLarry Finger printk(KERN_DEBUG PFX 36361e115a5SMichael Buesch "Core %d found: %s " 36461e115a5SMichael Buesch "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", 36561e115a5SMichael Buesch i, ssb_core_name(dev->id.coreid), 36661e115a5SMichael Buesch dev->id.coreid, dev->id.revision, dev->id.vendor); 36761e115a5SMichael Buesch 36861e115a5SMichael Buesch switch (dev->id.coreid) { 36961e115a5SMichael Buesch case SSB_DEV_80211: 37061e115a5SMichael Buesch nr_80211_cores++; 37161e115a5SMichael Buesch if (nr_80211_cores > 1) { 37261e115a5SMichael Buesch if (!we_support_multiple_80211_cores(bus)) { 37361e115a5SMichael Buesch ssb_dprintk(KERN_INFO PFX "Ignoring additional " 37461e115a5SMichael Buesch "802.11 core\n"); 37561e115a5SMichael Buesch continue; 37661e115a5SMichael Buesch } 37761e115a5SMichael Buesch } 37861e115a5SMichael Buesch break; 37961e115a5SMichael Buesch case SSB_DEV_EXTIF: 38061e115a5SMichael Buesch #ifdef CONFIG_SSB_DRIVER_EXTIF 38161e115a5SMichael Buesch if (bus->extif.dev) { 38261e115a5SMichael Buesch ssb_printk(KERN_WARNING PFX 38361e115a5SMichael Buesch "WARNING: Multiple EXTIFs found\n"); 38461e115a5SMichael Buesch break; 38561e115a5SMichael Buesch } 38661e115a5SMichael Buesch bus->extif.dev = dev; 38761e115a5SMichael Buesch #endif /* CONFIG_SSB_DRIVER_EXTIF */ 38861e115a5SMichael Buesch break; 38961e115a5SMichael Buesch case SSB_DEV_CHIPCOMMON: 39061e115a5SMichael Buesch if (bus->chipco.dev) { 39161e115a5SMichael Buesch ssb_printk(KERN_WARNING PFX 39261e115a5SMichael Buesch "WARNING: Multiple ChipCommon found\n"); 39361e115a5SMichael Buesch break; 39461e115a5SMichael Buesch } 39561e115a5SMichael Buesch bus->chipco.dev = dev; 39661e115a5SMichael Buesch break; 39761e115a5SMichael Buesch case SSB_DEV_MIPS: 39861e115a5SMichael Buesch case SSB_DEV_MIPS_3302: 39961e115a5SMichael Buesch #ifdef CONFIG_SSB_DRIVER_MIPS 40061e115a5SMichael Buesch if (bus->mipscore.dev) { 40161e115a5SMichael Buesch ssb_printk(KERN_WARNING PFX 40261e115a5SMichael Buesch "WARNING: Multiple MIPS cores found\n"); 40361e115a5SMichael Buesch break; 40461e115a5SMichael Buesch } 40561e115a5SMichael Buesch bus->mipscore.dev = dev; 40661e115a5SMichael Buesch #endif /* CONFIG_SSB_DRIVER_MIPS */ 40761e115a5SMichael Buesch break; 40861e115a5SMichael Buesch case SSB_DEV_PCI: 40961e115a5SMichael Buesch case SSB_DEV_PCIE: 41061e115a5SMichael Buesch #ifdef CONFIG_SSB_DRIVER_PCICORE 41187c4ac84SMichael Buesch if (bus->bustype == SSB_BUSTYPE_PCI) { 41287c4ac84SMichael Buesch /* Ignore PCI cores on PCI-E cards. 41387c4ac84SMichael Buesch * Ignore PCI-E cores on PCI cards. */ 41487c4ac84SMichael Buesch if (dev->id.coreid == SSB_DEV_PCI) { 4156b740aaaSHauke Mehrtens if (pci_is_pcie(bus->host_pci)) 41687c4ac84SMichael Buesch continue; 41787c4ac84SMichael Buesch } else { 4186b740aaaSHauke Mehrtens if (!pci_is_pcie(bus->host_pci)) 41987c4ac84SMichael Buesch continue; 42087c4ac84SMichael Buesch } 42187c4ac84SMichael Buesch } 42261e115a5SMichael Buesch if (bus->pcicore.dev) { 42361e115a5SMichael Buesch ssb_printk(KERN_WARNING PFX 42461e115a5SMichael Buesch "WARNING: Multiple PCI(E) cores found\n"); 42561e115a5SMichael Buesch break; 42661e115a5SMichael Buesch } 42761e115a5SMichael Buesch bus->pcicore.dev = dev; 42861e115a5SMichael Buesch #endif /* CONFIG_SSB_DRIVER_PCICORE */ 42961e115a5SMichael Buesch break; 430ed70c6e6SMichael Büsch case SSB_DEV_ETHERNET: 431ed70c6e6SMichael Büsch if (bus->bustype == SSB_BUSTYPE_PCI) { 432ed70c6e6SMichael Büsch if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && 433ed70c6e6SMichael Büsch (bus->host_pci->device & 0xFF00) == 0x4300) { 434ed70c6e6SMichael Büsch /* This is a dangling ethernet core on a 435ed70c6e6SMichael Büsch * wireless device. Ignore it. */ 436ed70c6e6SMichael Büsch continue; 437ed70c6e6SMichael Büsch } 438ed70c6e6SMichael Büsch } 439ed70c6e6SMichael Büsch break; 44061e115a5SMichael Buesch default: 44161e115a5SMichael Buesch break; 44261e115a5SMichael Buesch } 44361e115a5SMichael Buesch 44461e115a5SMichael Buesch dev_i++; 44561e115a5SMichael Buesch } 44661e115a5SMichael Buesch bus->nr_devices = dev_i; 44761e115a5SMichael Buesch 44861e115a5SMichael Buesch err = 0; 44961e115a5SMichael Buesch out: 45061e115a5SMichael Buesch return err; 45161e115a5SMichael Buesch err_unmap: 45261e115a5SMichael Buesch ssb_iounmap(bus); 45361e115a5SMichael Buesch goto out; 45461e115a5SMichael Buesch } 455