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 15b8b6069cSMichael Büsch #include "ssb_private.h" 16b8b6069cSMichael Büsch 1761e115a5SMichael Buesch #include <linux/ssb/ssb.h> 1861e115a5SMichael Buesch #include <linux/ssb/ssb_regs.h> 1961e115a5SMichael Buesch #include <linux/pci.h> 2061e115a5SMichael Buesch #include <linux/io.h> 2161e115a5SMichael Buesch 2261e115a5SMichael Buesch #include <pcmcia/cistpl.h> 2361e115a5SMichael Buesch #include <pcmcia/ds.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: 128b8b6069cSMichael Büsch dev_err(&pci_dev->dev, "PCI-ID not in fallback list\n"); 12961e115a5SMichael Buesch } 13061e115a5SMichael Buesch 13161e115a5SMichael Buesch return chipid_fallback; 13261e115a5SMichael Buesch } 13361e115a5SMichael Buesch 13461e115a5SMichael Buesch static u8 chipid_to_nrcores(u16 chipid) 13561e115a5SMichael Buesch { 13661e115a5SMichael Buesch switch (chipid) { 13761e115a5SMichael Buesch case 0x5365: 13861e115a5SMichael Buesch return 7; 13961e115a5SMichael Buesch case 0x4306: 14061e115a5SMichael Buesch return 6; 14161e115a5SMichael Buesch case 0x4310: 14261e115a5SMichael Buesch return 8; 14361e115a5SMichael Buesch case 0x4307: 14461e115a5SMichael Buesch case 0x4301: 14561e115a5SMichael Buesch return 5; 14661e115a5SMichael Buesch case 0x4401: 14761e115a5SMichael Buesch case 0x4402: 14861e115a5SMichael Buesch return 3; 14961e115a5SMichael Buesch case 0x4710: 15061e115a5SMichael Buesch case 0x4610: 15161e115a5SMichael Buesch case 0x4704: 15261e115a5SMichael Buesch return 9; 15361e115a5SMichael Buesch default: 154b8b6069cSMichael Büsch pr_err("CHIPID not in nrcores fallback list\n"); 15561e115a5SMichael Buesch } 15661e115a5SMichael Buesch 15761e115a5SMichael Buesch return 1; 15861e115a5SMichael Buesch } 15961e115a5SMichael Buesch 16061e115a5SMichael Buesch static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, 16161e115a5SMichael Buesch u16 offset) 16261e115a5SMichael Buesch { 163d8e23522SMartin Fuzzey u32 lo, hi; 164d8e23522SMartin Fuzzey 16561e115a5SMichael Buesch switch (bus->bustype) { 16661e115a5SMichael Buesch case SSB_BUSTYPE_SSB: 16761e115a5SMichael Buesch offset += current_coreidx * SSB_CORE_SIZE; 16861e115a5SMichael Buesch break; 16961e115a5SMichael Buesch case SSB_BUSTYPE_PCI: 17061e115a5SMichael Buesch break; 17161e115a5SMichael Buesch case SSB_BUSTYPE_PCMCIA: 17261e115a5SMichael Buesch if (offset >= 0x800) { 17361e115a5SMichael Buesch ssb_pcmcia_switch_segment(bus, 1); 17461e115a5SMichael Buesch offset -= 0x800; 17561e115a5SMichael Buesch } else 17661e115a5SMichael Buesch ssb_pcmcia_switch_segment(bus, 0); 177d8e23522SMartin Fuzzey lo = readw(bus->mmio + offset); 178d8e23522SMartin Fuzzey hi = readw(bus->mmio + offset + 2); 179d8e23522SMartin Fuzzey return lo | (hi << 16); 18024ea602eSAlbert Herranz case SSB_BUSTYPE_SDIO: 18124ea602eSAlbert Herranz offset += current_coreidx * SSB_CORE_SIZE; 18224ea602eSAlbert Herranz return ssb_sdio_scan_read32(bus, offset); 18361e115a5SMichael Buesch } 18461e115a5SMichael Buesch return readl(bus->mmio + offset); 18561e115a5SMichael Buesch } 18661e115a5SMichael Buesch 18761e115a5SMichael Buesch static int scan_switchcore(struct ssb_bus *bus, u8 coreidx) 18861e115a5SMichael Buesch { 18961e115a5SMichael Buesch switch (bus->bustype) { 19061e115a5SMichael Buesch case SSB_BUSTYPE_SSB: 19161e115a5SMichael Buesch break; 19261e115a5SMichael Buesch case SSB_BUSTYPE_PCI: 19361e115a5SMichael Buesch return ssb_pci_switch_coreidx(bus, coreidx); 19461e115a5SMichael Buesch case SSB_BUSTYPE_PCMCIA: 19561e115a5SMichael Buesch return ssb_pcmcia_switch_coreidx(bus, coreidx); 19624ea602eSAlbert Herranz case SSB_BUSTYPE_SDIO: 19724ea602eSAlbert Herranz return ssb_sdio_scan_switch_coreidx(bus, coreidx); 19861e115a5SMichael Buesch } 19961e115a5SMichael Buesch return 0; 20061e115a5SMichael Buesch } 20161e115a5SMichael Buesch 20261e115a5SMichael Buesch void ssb_iounmap(struct ssb_bus *bus) 20361e115a5SMichael Buesch { 20461e115a5SMichael Buesch switch (bus->bustype) { 20561e115a5SMichael Buesch case SSB_BUSTYPE_SSB: 20661e115a5SMichael Buesch case SSB_BUSTYPE_PCMCIA: 20761e115a5SMichael Buesch iounmap(bus->mmio); 20861e115a5SMichael Buesch break; 20961e115a5SMichael Buesch case SSB_BUSTYPE_PCI: 21061e115a5SMichael Buesch #ifdef CONFIG_SSB_PCIHOST 21161e115a5SMichael Buesch pci_iounmap(bus->host_pci, bus->mmio); 21261e115a5SMichael Buesch #else 21361e115a5SMichael Buesch SSB_BUG_ON(1); /* Can't reach this code. */ 21461e115a5SMichael Buesch #endif 21561e115a5SMichael Buesch break; 21624ea602eSAlbert Herranz case SSB_BUSTYPE_SDIO: 21724ea602eSAlbert Herranz break; 21861e115a5SMichael Buesch } 21961e115a5SMichael Buesch bus->mmio = NULL; 22061e115a5SMichael Buesch bus->mapped_device = NULL; 22161e115a5SMichael Buesch } 22261e115a5SMichael Buesch 22361e115a5SMichael Buesch static void __iomem *ssb_ioremap(struct ssb_bus *bus, 22461e115a5SMichael Buesch unsigned long baseaddr) 22561e115a5SMichael Buesch { 22661e115a5SMichael Buesch void __iomem *mmio = NULL; 22761e115a5SMichael Buesch 22861e115a5SMichael Buesch switch (bus->bustype) { 22961e115a5SMichael Buesch case SSB_BUSTYPE_SSB: 23061e115a5SMichael Buesch /* Only map the first core for now. */ 23161e115a5SMichael Buesch /* fallthrough... */ 23261e115a5SMichael Buesch case SSB_BUSTYPE_PCMCIA: 23361e115a5SMichael Buesch mmio = ioremap(baseaddr, SSB_CORE_SIZE); 23461e115a5SMichael Buesch break; 23561e115a5SMichael Buesch case SSB_BUSTYPE_PCI: 23661e115a5SMichael Buesch #ifdef CONFIG_SSB_PCIHOST 23761e115a5SMichael Buesch mmio = pci_iomap(bus->host_pci, 0, ~0UL); 23861e115a5SMichael Buesch #else 23961e115a5SMichael Buesch SSB_BUG_ON(1); /* Can't reach this code. */ 24061e115a5SMichael Buesch #endif 24161e115a5SMichael Buesch break; 24224ea602eSAlbert Herranz case SSB_BUSTYPE_SDIO: 24324ea602eSAlbert Herranz /* Nothing to ioremap in the SDIO case, just fake it */ 24424ea602eSAlbert Herranz mmio = (void __iomem *)baseaddr; 24524ea602eSAlbert Herranz break; 24661e115a5SMichael Buesch } 24761e115a5SMichael Buesch 24861e115a5SMichael Buesch return mmio; 24961e115a5SMichael Buesch } 25061e115a5SMichael Buesch 25161e115a5SMichael Buesch static int we_support_multiple_80211_cores(struct ssb_bus *bus) 25261e115a5SMichael Buesch { 25361e115a5SMichael Buesch /* More than one 802.11 core is only supported by special chips. 25461e115a5SMichael Buesch * There are chips with two 802.11 cores, but with dangling 25561e115a5SMichael Buesch * pins on the second core. Be careful and reject them here. 25661e115a5SMichael Buesch */ 25761e115a5SMichael Buesch 25861e115a5SMichael Buesch #ifdef CONFIG_SSB_PCIHOST 25961e115a5SMichael Buesch if (bus->bustype == SSB_BUSTYPE_PCI) { 26061e115a5SMichael Buesch if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && 2619fcce61cSRafał Miłecki ((bus->host_pci->device == 0x4313) || 2629fcce61cSRafał Miłecki (bus->host_pci->device == 0x431A) || 2639fcce61cSRafał Miłecki (bus->host_pci->device == 0x4321) || 2649fcce61cSRafał Miłecki (bus->host_pci->device == 0x4324))) 26561e115a5SMichael Buesch return 1; 26661e115a5SMichael Buesch } 26761e115a5SMichael Buesch #endif /* CONFIG_SSB_PCIHOST */ 26861e115a5SMichael Buesch return 0; 26961e115a5SMichael Buesch } 27061e115a5SMichael Buesch 27161e115a5SMichael Buesch int ssb_bus_scan(struct ssb_bus *bus, 27261e115a5SMichael Buesch unsigned long baseaddr) 27361e115a5SMichael Buesch { 27461e115a5SMichael Buesch int err = -ENOMEM; 27561e115a5SMichael Buesch void __iomem *mmio; 27661e115a5SMichael Buesch u32 idhi, cc, rev, tmp; 27761e115a5SMichael Buesch int dev_i, i; 27861e115a5SMichael Buesch struct ssb_device *dev; 27961e115a5SMichael Buesch int nr_80211_cores = 0; 28061e115a5SMichael Buesch 28161e115a5SMichael Buesch mmio = ssb_ioremap(bus, baseaddr); 28261e115a5SMichael Buesch if (!mmio) 28361e115a5SMichael Buesch goto out; 28461e115a5SMichael Buesch bus->mmio = mmio; 28561e115a5SMichael Buesch 28661e115a5SMichael Buesch err = scan_switchcore(bus, 0); /* Switch to first core */ 28761e115a5SMichael Buesch if (err) 28861e115a5SMichael Buesch goto err_unmap; 28961e115a5SMichael Buesch 29061e115a5SMichael Buesch idhi = scan_read32(bus, 0, SSB_IDHIGH); 29161e115a5SMichael Buesch cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT; 29261e115a5SMichael Buesch rev = (idhi & SSB_IDHIGH_RCLO); 29361e115a5SMichael Buesch rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT; 29461e115a5SMichael Buesch 29561e115a5SMichael Buesch bus->nr_devices = 0; 29661e115a5SMichael Buesch if (cc == SSB_DEV_CHIPCOMMON) { 29761e115a5SMichael Buesch tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID); 29861e115a5SMichael Buesch 29961e115a5SMichael Buesch bus->chip_id = (tmp & SSB_CHIPCO_IDMASK); 30061e115a5SMichael Buesch bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >> 30161e115a5SMichael Buesch SSB_CHIPCO_REVSHIFT; 30261e115a5SMichael Buesch bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >> 30361e115a5SMichael Buesch SSB_CHIPCO_PACKSHIFT; 30461e115a5SMichael Buesch if (rev >= 4) { 30561e115a5SMichael Buesch bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >> 30661e115a5SMichael Buesch SSB_CHIPCO_NRCORESSHIFT; 30761e115a5SMichael Buesch } 30861e115a5SMichael Buesch tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP); 30961e115a5SMichael Buesch bus->chipco.capabilities = tmp; 31061e115a5SMichael Buesch } else { 31161e115a5SMichael Buesch if (bus->bustype == SSB_BUSTYPE_PCI) { 31261e115a5SMichael Buesch bus->chip_id = pcidev_to_chipid(bus->host_pci); 313ce2dd3c2SSergei Shtylyov bus->chip_rev = bus->host_pci->revision; 31461e115a5SMichael Buesch bus->chip_package = 0; 31561e115a5SMichael Buesch } else { 31661e115a5SMichael Buesch bus->chip_id = 0x4710; 31761e115a5SMichael Buesch bus->chip_rev = 0; 31861e115a5SMichael Buesch bus->chip_package = 0; 31961e115a5SMichael Buesch } 32061e115a5SMichael Buesch } 321b8b6069cSMichael Büsch pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", 32233a606acSJoe Perches bus->chip_id, bus->chip_rev, bus->chip_package); 32361e115a5SMichael Buesch if (!bus->nr_devices) 32461e115a5SMichael Buesch bus->nr_devices = chipid_to_nrcores(bus->chip_id); 32561e115a5SMichael Buesch if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { 326b8b6069cSMichael Büsch pr_err("More than %d ssb cores found (%d)\n", 32761e115a5SMichael Buesch SSB_MAX_NR_CORES, bus->nr_devices); 32861e115a5SMichael Buesch goto err_unmap; 32961e115a5SMichael Buesch } 33061e115a5SMichael Buesch if (bus->bustype == SSB_BUSTYPE_SSB) { 33161e115a5SMichael Buesch /* Now that we know the number of cores, 33261e115a5SMichael Buesch * remap the whole IO space for all cores. 33361e115a5SMichael Buesch */ 33461e115a5SMichael Buesch err = -ENOMEM; 33561e115a5SMichael Buesch iounmap(mmio); 33661e115a5SMichael Buesch mmio = ioremap(baseaddr, SSB_CORE_SIZE * bus->nr_devices); 33761e115a5SMichael Buesch if (!mmio) 33861e115a5SMichael Buesch goto out; 33961e115a5SMichael Buesch bus->mmio = mmio; 34061e115a5SMichael Buesch } 34161e115a5SMichael Buesch 34261e115a5SMichael Buesch /* Fetch basic information about each core/device */ 34361e115a5SMichael Buesch for (i = 0, dev_i = 0; i < bus->nr_devices; i++) { 34461e115a5SMichael Buesch err = scan_switchcore(bus, i); 34561e115a5SMichael Buesch if (err) 34661e115a5SMichael Buesch goto err_unmap; 34761e115a5SMichael Buesch dev = &(bus->devices[dev_i]); 34861e115a5SMichael Buesch 34961e115a5SMichael Buesch idhi = scan_read32(bus, i, SSB_IDHIGH); 35061e115a5SMichael Buesch dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT; 35161e115a5SMichael Buesch dev->id.revision = (idhi & SSB_IDHIGH_RCLO); 35261e115a5SMichael Buesch dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT; 35361e115a5SMichael Buesch dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT; 35461e115a5SMichael Buesch dev->core_index = i; 35561e115a5SMichael Buesch dev->bus = bus; 35661e115a5SMichael Buesch dev->ops = bus->ops; 35761e115a5SMichael Buesch 358b8b6069cSMichael Büsch pr_debug("Core %d found: %s (cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", 35961e115a5SMichael Buesch i, ssb_core_name(dev->id.coreid), 36061e115a5SMichael Buesch dev->id.coreid, dev->id.revision, dev->id.vendor); 36161e115a5SMichael Buesch 36261e115a5SMichael Buesch switch (dev->id.coreid) { 36361e115a5SMichael Buesch case SSB_DEV_80211: 36461e115a5SMichael Buesch nr_80211_cores++; 36561e115a5SMichael Buesch if (nr_80211_cores > 1) { 36661e115a5SMichael Buesch if (!we_support_multiple_80211_cores(bus)) { 367b8b6069cSMichael Büsch pr_debug("Ignoring additional 802.11 core\n"); 36861e115a5SMichael Buesch continue; 36961e115a5SMichael Buesch } 37061e115a5SMichael Buesch } 37161e115a5SMichael Buesch break; 37261e115a5SMichael Buesch case SSB_DEV_EXTIF: 37361e115a5SMichael Buesch #ifdef CONFIG_SSB_DRIVER_EXTIF 37461e115a5SMichael Buesch if (bus->extif.dev) { 375b8b6069cSMichael Büsch pr_warn("WARNING: Multiple EXTIFs found\n"); 37661e115a5SMichael Buesch break; 37761e115a5SMichael Buesch } 37861e115a5SMichael Buesch bus->extif.dev = dev; 37961e115a5SMichael Buesch #endif /* CONFIG_SSB_DRIVER_EXTIF */ 38061e115a5SMichael Buesch break; 38161e115a5SMichael Buesch case SSB_DEV_CHIPCOMMON: 38261e115a5SMichael Buesch if (bus->chipco.dev) { 383b8b6069cSMichael Büsch pr_warn("WARNING: Multiple ChipCommon found\n"); 38461e115a5SMichael Buesch break; 38561e115a5SMichael Buesch } 38661e115a5SMichael Buesch bus->chipco.dev = dev; 38761e115a5SMichael Buesch break; 38861e115a5SMichael Buesch case SSB_DEV_MIPS: 38961e115a5SMichael Buesch case SSB_DEV_MIPS_3302: 39061e115a5SMichael Buesch #ifdef CONFIG_SSB_DRIVER_MIPS 39161e115a5SMichael Buesch if (bus->mipscore.dev) { 392b8b6069cSMichael Büsch pr_warn("WARNING: Multiple MIPS cores found\n"); 39361e115a5SMichael Buesch break; 39461e115a5SMichael Buesch } 39561e115a5SMichael Buesch bus->mipscore.dev = dev; 39661e115a5SMichael Buesch #endif /* CONFIG_SSB_DRIVER_MIPS */ 39761e115a5SMichael Buesch break; 39861e115a5SMichael Buesch case SSB_DEV_PCI: 39961e115a5SMichael Buesch case SSB_DEV_PCIE: 40061e115a5SMichael Buesch #ifdef CONFIG_SSB_DRIVER_PCICORE 40187c4ac84SMichael Buesch if (bus->bustype == SSB_BUSTYPE_PCI) { 40287c4ac84SMichael Buesch /* Ignore PCI cores on PCI-E cards. 40387c4ac84SMichael Buesch * Ignore PCI-E cores on PCI cards. */ 40487c4ac84SMichael Buesch if (dev->id.coreid == SSB_DEV_PCI) { 4056b740aaaSHauke Mehrtens if (pci_is_pcie(bus->host_pci)) 40687c4ac84SMichael Buesch continue; 40787c4ac84SMichael Buesch } else { 4086b740aaaSHauke Mehrtens if (!pci_is_pcie(bus->host_pci)) 40987c4ac84SMichael Buesch continue; 41087c4ac84SMichael Buesch } 41187c4ac84SMichael Buesch } 41261e115a5SMichael Buesch if (bus->pcicore.dev) { 413b8b6069cSMichael Büsch pr_warn("WARNING: Multiple PCI(E) cores found\n"); 41461e115a5SMichael Buesch break; 41561e115a5SMichael Buesch } 41661e115a5SMichael Buesch bus->pcicore.dev = dev; 41761e115a5SMichael Buesch #endif /* CONFIG_SSB_DRIVER_PCICORE */ 41861e115a5SMichael Buesch break; 419ed70c6e6SMichael Büsch case SSB_DEV_ETHERNET: 420ed70c6e6SMichael Büsch if (bus->bustype == SSB_BUSTYPE_PCI) { 421ed70c6e6SMichael Büsch if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && 422ed70c6e6SMichael Büsch (bus->host_pci->device & 0xFF00) == 0x4300) { 423ed70c6e6SMichael Büsch /* This is a dangling ethernet core on a 424ed70c6e6SMichael Büsch * wireless device. Ignore it. */ 425ed70c6e6SMichael Büsch continue; 426ed70c6e6SMichael Büsch } 427ed70c6e6SMichael Büsch } 428ed70c6e6SMichael Büsch break; 42961e115a5SMichael Buesch default: 43061e115a5SMichael Buesch break; 43161e115a5SMichael Buesch } 43261e115a5SMichael Buesch 43361e115a5SMichael Buesch dev_i++; 43461e115a5SMichael Buesch } 43561e115a5SMichael Buesch bus->nr_devices = dev_i; 43661e115a5SMichael Buesch 43761e115a5SMichael Buesch err = 0; 43861e115a5SMichael Buesch out: 43961e115a5SMichael Buesch return err; 44061e115a5SMichael Buesch err_unmap: 44161e115a5SMichael Buesch ssb_iounmap(bus); 44261e115a5SMichael Buesch goto out; 44361e115a5SMichael Buesch } 444