Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --- build_dir/linux-brcm47xx/linux-2.6.32.9/drivers/ssb/scan_old.c 2010-02-23 18:38:51.000000000 +0300
- +++ build_dir/linux-brcm47xx/linux-2.6.32.9/drivers/ssb/scan_old1.c 2010-03-20 02:34:09.000000000 +0300
- @@ -1,439 +1,808 @@
- -/*
- - * Sonics Silicon Backplane
- - * Bus scanning
- - *
- - * Copyright (C) 2005-2007 Michael Buesch <mb@bu3sch.de>
- - * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
- - * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
- - * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
- - * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
- - * Copyright (C) 2006 Broadcom Corporation.
- - *
- - * Licensed under the GNU/GPL. See COPYING for details.
- - */
- -
- -#include <linux/ssb/ssb.h>
- -#include <linux/ssb/ssb_regs.h>
- -#include <linux/pci.h>
- -#include <linux/io.h>
- -
- -#include <pcmcia/cs_types.h>
- -#include <pcmcia/cs.h>
- -#include <pcmcia/cistpl.h>
- -#include <pcmcia/ds.h>
- -
- -#include "ssb_private.h"
- -
- -
- -const char *ssb_core_name(u16 coreid)
- -{
- - switch (coreid) {
- - case SSB_DEV_CHIPCOMMON:
- - return "ChipCommon";
- - case SSB_DEV_ILINE20:
- - return "ILine 20";
- - case SSB_DEV_SDRAM:
- - return "SDRAM";
- - case SSB_DEV_PCI:
- - return "PCI";
- - case SSB_DEV_MIPS:
- - return "MIPS";
- - case SSB_DEV_ETHERNET:
- - return "Fast Ethernet";
- - case SSB_DEV_V90:
- - return "V90";
- - case SSB_DEV_USB11_HOSTDEV:
- - return "USB 1.1 Hostdev";
- - case SSB_DEV_ADSL:
- - return "ADSL";
- - case SSB_DEV_ILINE100:
- - return "ILine 100";
- - case SSB_DEV_IPSEC:
- - return "IPSEC";
- - case SSB_DEV_PCMCIA:
- - return "PCMCIA";
- - case SSB_DEV_INTERNAL_MEM:
- - return "Internal Memory";
- - case SSB_DEV_MEMC_SDRAM:
- - return "MEMC SDRAM";
- - case SSB_DEV_EXTIF:
- - return "EXTIF";
- - case SSB_DEV_80211:
- - return "IEEE 802.11";
- - case SSB_DEV_MIPS_3302:
- - return "MIPS 3302";
- - case SSB_DEV_USB11_HOST:
- - return "USB 1.1 Host";
- - case SSB_DEV_USB11_DEV:
- - return "USB 1.1 Device";
- - case SSB_DEV_USB20_HOST:
- - return "USB 2.0 Host";
- - case SSB_DEV_USB20_DEV:
- - return "USB 2.0 Device";
- - case SSB_DEV_SDIO_HOST:
- - return "SDIO Host";
- - case SSB_DEV_ROBOSWITCH:
- - return "Roboswitch";
- - case SSB_DEV_PARA_ATA:
- - return "PATA";
- - case SSB_DEV_SATA_XORDMA:
- - return "SATA XOR-DMA";
- - case SSB_DEV_ETHERNET_GBIT:
- - return "GBit Ethernet";
- - case SSB_DEV_PCIE:
- - return "PCI-E";
- - case SSB_DEV_MIMO_PHY:
- - return "MIMO PHY";
- - case SSB_DEV_SRAM_CTRLR:
- - return "SRAM Controller";
- - case SSB_DEV_MINI_MACPHY:
- - return "Mini MACPHY";
- - case SSB_DEV_ARM_1176:
- - return "ARM 1176";
- - case SSB_DEV_ARM_7TDMI:
- - return "ARM 7TDMI";
- - }
- - return "UNKNOWN";
- -}
- -
- -static u16 pcidev_to_chipid(struct pci_dev *pci_dev)
- -{
- - u16 chipid_fallback = 0;
- -
- - switch (pci_dev->device) {
- - case 0x4301:
- - chipid_fallback = 0x4301;
- - break;
- - case 0x4305 ... 0x4307:
- - chipid_fallback = 0x4307;
- - break;
- - case 0x4403:
- - chipid_fallback = 0x4402;
- - break;
- - case 0x4610 ... 0x4615:
- - chipid_fallback = 0x4610;
- - break;
- - case 0x4710 ... 0x4715:
- - chipid_fallback = 0x4710;
- - break;
- - case 0x4320 ... 0x4325:
- - chipid_fallback = 0x4309;
- - break;
- - case PCI_DEVICE_ID_BCM4401:
- - case PCI_DEVICE_ID_BCM4401B0:
- - case PCI_DEVICE_ID_BCM4401B1:
- - chipid_fallback = 0x4401;
- - break;
- - default:
- - ssb_printk(KERN_ERR PFX
- - "PCI-ID not in fallback list\n");
- - }
- -
- - return chipid_fallback;
- -}
- -
- -static u8 chipid_to_nrcores(u16 chipid)
- -{
- - switch (chipid) {
- - case 0x5365:
- - return 7;
- - case 0x4306:
- - return 6;
- - case 0x4310:
- - return 8;
- - case 0x4307:
- - case 0x4301:
- - return 5;
- - case 0x4401:
- - case 0x4402:
- - return 3;
- - case 0x4710:
- - case 0x4610:
- - case 0x4704:
- - return 9;
- - default:
- - ssb_printk(KERN_ERR PFX
- - "CHIPID not in nrcores fallback list\n");
- - }
- -
- - return 1;
- -}
- -
- -static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx,
- - u16 offset)
- -{
- - u32 lo, hi;
- -
- - switch (bus->bustype) {
- - case SSB_BUSTYPE_SSB:
- - offset += current_coreidx * SSB_CORE_SIZE;
- - break;
- - case SSB_BUSTYPE_PCI:
- - break;
- - case SSB_BUSTYPE_PCMCIA:
- - if (offset >= 0x800) {
- - ssb_pcmcia_switch_segment(bus, 1);
- - offset -= 0x800;
- - } else
- - ssb_pcmcia_switch_segment(bus, 0);
- - lo = readw(bus->mmio + offset);
- - hi = readw(bus->mmio + offset + 2);
- - return lo | (hi << 16);
- - case SSB_BUSTYPE_SDIO:
- - offset += current_coreidx * SSB_CORE_SIZE;
- - return ssb_sdio_scan_read32(bus, offset);
- - }
- - return readl(bus->mmio + offset);
- -}
- -
- -static int scan_switchcore(struct ssb_bus *bus, u8 coreidx)
- -{
- - switch (bus->bustype) {
- - case SSB_BUSTYPE_SSB:
- - break;
- - case SSB_BUSTYPE_PCI:
- - return ssb_pci_switch_coreidx(bus, coreidx);
- - case SSB_BUSTYPE_PCMCIA:
- - return ssb_pcmcia_switch_coreidx(bus, coreidx);
- - case SSB_BUSTYPE_SDIO:
- - return ssb_sdio_scan_switch_coreidx(bus, coreidx);
- - }
- - return 0;
- -}
- -
- -void ssb_iounmap(struct ssb_bus *bus)
- -{
- - switch (bus->bustype) {
- - case SSB_BUSTYPE_SSB:
- - case SSB_BUSTYPE_PCMCIA:
- - iounmap(bus->mmio);
- - break;
- - case SSB_BUSTYPE_PCI:
- -#ifdef CONFIG_SSB_PCIHOST
- - pci_iounmap(bus->host_pci, bus->mmio);
- -#else
- - SSB_BUG_ON(1); /* Can't reach this code. */
- -#endif
- - break;
- - case SSB_BUSTYPE_SDIO:
- - break;
- - }
- - bus->mmio = NULL;
- - bus->mapped_device = NULL;
- -}
- -
- -static void __iomem *ssb_ioremap(struct ssb_bus *bus,
- - unsigned long baseaddr)
- -{
- - void __iomem *mmio = NULL;
- -
- - switch (bus->bustype) {
- - case SSB_BUSTYPE_SSB:
- - /* Only map the first core for now. */
- - /* fallthrough... */
- - case SSB_BUSTYPE_PCMCIA:
- - mmio = ioremap(baseaddr, SSB_CORE_SIZE);
- - break;
- - case SSB_BUSTYPE_PCI:
- -#ifdef CONFIG_SSB_PCIHOST
- - mmio = pci_iomap(bus->host_pci, 0, ~0UL);
- -#else
- - SSB_BUG_ON(1); /* Can't reach this code. */
- -#endif
- - break;
- - case SSB_BUSTYPE_SDIO:
- - /* Nothing to ioremap in the SDIO case, just fake it */
- - mmio = (void __iomem *)baseaddr;
- - break;
- - }
- -
- - return mmio;
- -}
- -
- -static int we_support_multiple_80211_cores(struct ssb_bus *bus)
- -{
- - /* More than one 802.11 core is only supported by special chips.
- - * There are chips with two 802.11 cores, but with dangling
- - * pins on the second core. Be careful and reject them here.
- - */
- -
- -#ifdef CONFIG_SSB_PCIHOST
- - if (bus->bustype == SSB_BUSTYPE_PCI) {
- - if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM &&
- - bus->host_pci->device == 0x4324)
- - return 1;
- - }
- -#endif /* CONFIG_SSB_PCIHOST */
- - return 0;
- -}
- -
- -int ssb_bus_scan(struct ssb_bus *bus,
- - unsigned long baseaddr)
- -{
- - int err = -ENOMEM;
- - void __iomem *mmio;
- - u32 idhi, cc, rev, tmp;
- - int dev_i, i;
- - struct ssb_device *dev;
- - int nr_80211_cores = 0;
- -
- - mmio = ssb_ioremap(bus, baseaddr);
- - if (!mmio)
- - goto out;
- - bus->mmio = mmio;
- -
- - err = scan_switchcore(bus, 0); /* Switch to first core */
- - if (err)
- - goto err_unmap;
- -
- - idhi = scan_read32(bus, 0, SSB_IDHIGH);
- - cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
- - rev = (idhi & SSB_IDHIGH_RCLO);
- - rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
- -
- - bus->nr_devices = 0;
- - if (cc == SSB_DEV_CHIPCOMMON) {
- - tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID);
- -
- - bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
- - bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >>
- - SSB_CHIPCO_REVSHIFT;
- - bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >>
- - SSB_CHIPCO_PACKSHIFT;
- - if (rev >= 4) {
- - bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >>
- - SSB_CHIPCO_NRCORESSHIFT;
- - }
- - tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP);
- - bus->chipco.capabilities = tmp;
- - } else {
- - if (bus->bustype == SSB_BUSTYPE_PCI) {
- - bus->chip_id = pcidev_to_chipid(bus->host_pci);
- - pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
- - &bus->chip_rev);
- - bus->chip_package = 0;
- - } else {
- - bus->chip_id = 0x4710;
- - bus->chip_rev = 0;
- - bus->chip_package = 0;
- - }
- - }
- - if (!bus->nr_devices)
- - bus->nr_devices = chipid_to_nrcores(bus->chip_id);
- - if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
- - ssb_printk(KERN_ERR PFX
- - "More than %d ssb cores found (%d)\n",
- - SSB_MAX_NR_CORES, bus->nr_devices);
- - goto err_unmap;
- - }
- - if (bus->bustype == SSB_BUSTYPE_SSB) {
- - /* Now that we know the number of cores,
- - * remap the whole IO space for all cores.
- - */
- - err = -ENOMEM;
- - iounmap(mmio);
- - mmio = ioremap(baseaddr, SSB_CORE_SIZE * bus->nr_devices);
- - if (!mmio)
- - goto out;
- - bus->mmio = mmio;
- - }
- -
- - /* Fetch basic information about each core/device */
- - for (i = 0, dev_i = 0; i < bus->nr_devices; i++) {
- - err = scan_switchcore(bus, i);
- - if (err)
- - goto err_unmap;
- - dev = &(bus->devices[dev_i]);
- -
- - idhi = scan_read32(bus, i, SSB_IDHIGH);
- - dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
- - dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
- - dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
- - dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
- - dev->core_index = i;
- - dev->bus = bus;
- - dev->ops = bus->ops;
- -
- - ssb_dprintk(KERN_INFO PFX
- - "Core %d found: %s "
- - "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",
- - i, ssb_core_name(dev->id.coreid),
- - dev->id.coreid, dev->id.revision, dev->id.vendor);
- -
- - switch (dev->id.coreid) {
- - case SSB_DEV_80211:
- - nr_80211_cores++;
- - if (nr_80211_cores > 1) {
- - if (!we_support_multiple_80211_cores(bus)) {
- - ssb_dprintk(KERN_INFO PFX "Ignoring additional "
- - "802.11 core\n");
- - continue;
- - }
- - }
- - break;
- - case SSB_DEV_EXTIF:
- -#ifdef CONFIG_SSB_DRIVER_EXTIF
- - if (bus->extif.dev) {
- - ssb_printk(KERN_WARNING PFX
- - "WARNING: Multiple EXTIFs found\n");
- - break;
- - }
- - bus->extif.dev = dev;
- -#endif /* CONFIG_SSB_DRIVER_EXTIF */
- - break;
- - case SSB_DEV_CHIPCOMMON:
- - if (bus->chipco.dev) {
- - ssb_printk(KERN_WARNING PFX
- - "WARNING: Multiple ChipCommon found\n");
- - break;
- - }
- - bus->chipco.dev = dev;
- - break;
- - case SSB_DEV_MIPS:
- - case SSB_DEV_MIPS_3302:
- -#ifdef CONFIG_SSB_DRIVER_MIPS
- - if (bus->mipscore.dev) {
- - ssb_printk(KERN_WARNING PFX
- - "WARNING: Multiple MIPS cores found\n");
- - break;
- - }
- - bus->mipscore.dev = dev;
- -#endif /* CONFIG_SSB_DRIVER_MIPS */
- - break;
- - case SSB_DEV_PCI:
- - case SSB_DEV_PCIE:
- -#ifdef CONFIG_SSB_DRIVER_PCICORE
- - if (bus->bustype == SSB_BUSTYPE_PCI) {
- - /* Ignore PCI cores on PCI-E cards.
- - * Ignore PCI-E cores on PCI cards. */
- - if (dev->id.coreid == SSB_DEV_PCI) {
- - if (bus->host_pci->is_pcie)
- - continue;
- - } else {
- - if (!bus->host_pci->is_pcie)
- - continue;
- - }
- - }
- - if (bus->pcicore.dev) {
- - ssb_printk(KERN_WARNING PFX
- - "WARNING: Multiple PCI(E) cores found\n");
- - break;
- - }
- - bus->pcicore.dev = dev;
- -#endif /* CONFIG_SSB_DRIVER_PCICORE */
- - break;
- - default:
- - break;
- - }
- -
- - dev_i++;
- - }
- - bus->nr_devices = dev_i;
- -
- - err = 0;
- -out:
- - return err;
- -err_unmap:
- - ssb_iounmap(bus);
- - goto out;
- -}
- +/*
- + * Sonics Silicon Backplane
- + * Bus scanning
- + *
- + * Copyright (C) 2005-2007 Michael Buesch <mb@bu3sch.de>
- + * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
- + * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
- + * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
- + * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
- + * Copyright (C) 2006 Broadcom Corporation.
- + *
- + * Licensed under the GNU/GPL. See COPYING for details.
- + */
- +
- +#include <linux/ssb/ssb.h>
- +#include <linux/ssb/ssb_regs.h>
- +#include <linux/pci.h>
- +#include <linux/io.h>
- +
- +#include <pcmcia/cs_types.h>
- +#include <pcmcia/cs.h>
- +#include <pcmcia/cistpl.h>
- +#include <pcmcia/ds.h>
- +
- +#include "ssb_private.h"
- +
- +
- +const char *ssb_core_name(u16 coreid)
- +{
- + switch (coreid) {
- + case SSB_DEV_CHIPCOMMON:
- + return "ChipCommon";
- + case SSB_DEV_ILINE20:
- + return "ILine 20";
- + case SSB_DEV_SDRAM:
- + return "SDRAM";
- + case SSB_DEV_PCI:
- + return "PCI";
- + case SSB_DEV_MIPS:
- + return "MIPS";
- + case SSB_DEV_ETHERNET:
- + return "Fast Ethernet";
- + case SSB_DEV_V90:
- + return "V90";
- + case SSB_DEV_USB11_HOSTDEV:
- + return "USB 1.1 Hostdev";
- + case SSB_DEV_ADSL:
- + return "ADSL";
- + case SSB_DEV_ILINE100:
- + return "ILine 100";
- + case SSB_DEV_IPSEC:
- + return "IPSEC";
- + case SSB_DEV_PCMCIA:
- + return "PCMCIA";
- + case SSB_DEV_INTERNAL_MEM:
- + return "Internal Memory";
- + case SSB_DEV_MEMC_SDRAM:
- + return "MEMC SDRAM";
- + case SSB_DEV_EXTIF:
- + return "EXTIF";
- + case SSB_DEV_80211:
- + return "IEEE 802.11";
- + case SSB_DEV_MIPS_3302:
- + return "MIPS 3302";
- + case SSB_DEV_USB11_HOST:
- + return "USB 1.1 Host";
- + case SSB_DEV_USB11_DEV:
- + return "USB 1.1 Device";
- + case SSB_DEV_USB20_HOST:
- + return "USB 2.0 Host";
- + case SSB_DEV_USB20_DEV:
- + return "USB 2.0 Device";
- + case SSB_DEV_SDIO_HOST:
- + return "SDIO Host";
- + case SSB_DEV_ROBOSWITCH:
- + return "Roboswitch";
- + case SSB_DEV_PARA_ATA:
- + return "PATA";
- + case SSB_DEV_SATA_XORDMA:
- + return "SATA XOR-DMA";
- + case SSB_DEV_ETHERNET_GBIT:
- + return "GBit Ethernet";
- + case SSB_DEV_PCIE:
- + return "PCI-E";
- + case SSB_DEV_MIMO_PHY:
- + return "MIMO PHY";
- + case SSB_DEV_SRAM_CTRLR:
- + return "SRAM Controller";
- + case SSB_DEV_MINI_MACPHY:
- + return "Mini MACPHY";
- + case SSB_DEV_ARM_1176:
- + return "ARM 1176";
- + case SSB_DEV_ARM_7TDMI:
- + return "ARM 7TDMI";
- + }
- + return "UNKNOWN";
- +}
- +
- +static u16 pcidev_to_chipid(struct pci_dev *pci_dev)
- +{
- + u16 chipid_fallback = 0;
- +
- + switch (pci_dev->device) {
- + case 0x4301:
- + chipid_fallback = 0x4301;
- + break;
- + case 0x4305 ... 0x4307:
- + chipid_fallback = 0x4307;
- + break;
- + case 0x4403:
- + chipid_fallback = 0x4402;
- + break;
- + case 0x4610 ... 0x4615:
- + chipid_fallback = 0x4610;
- + break;
- + case 0x4710 ... 0x4715:
- + chipid_fallback = 0x4710;
- + break;
- + case 0x4320 ... 0x4325:
- + chipid_fallback = 0x4309;
- + break;
- + case PCI_DEVICE_ID_BCM4401:
- + case PCI_DEVICE_ID_BCM4401B0:
- + case PCI_DEVICE_ID_BCM4401B1:
- + chipid_fallback = 0x4401;
- + break;
- + default:
- + ssb_printk(KERN_ERR PFX
- + "PCI-ID not in fallback list\n");
- + }
- +
- + return chipid_fallback;
- +}
- +
- +static u8 chipid_to_nrcores(u16 chipid)
- +{
- + switch (chipid) {
- + case 0x5365:
- + return 7;
- + case 0x4306:
- + return 6;
- + case 0x4310:
- + return 8;
- + case 0x4307:
- + case 0x4301:
- + return 5;
- + case 0x4401:
- + case 0x4402:
- + return 3;
- + case 0x4710:
- + case 0x4610:
- + case 0x4704:
- + return 9;
- + default:
- + ssb_printk(KERN_ERR PFX
- + "CHIPID not in nrcores fallback list\n");
- + }
- +
- + return 1;
- +}
- +
- +static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx,
- + u16 offset)
- +{
- + u32 lo, hi;
- +
- + switch (bus->bustype) {
- + case SSB_BUSTYPE_SSB:
- + printk("asdf\n");
- + offset += current_coreidx * SSB_CORE_SIZE;
- + break;
- + case SSB_BUSTYPE_PCI:
- + break;
- + case SSB_BUSTYPE_PCMCIA:
- + if (offset >= 0x800) {
- + ssb_pcmcia_switch_segment(bus, 1);
- + offset -= 0x800;
- + } else
- + ssb_pcmcia_switch_segment(bus, 0);
- + lo = readw(bus->mmio + offset);
- + hi = readw(bus->mmio + offset + 2);
- + return lo | (hi << 16);
- + case SSB_BUSTYPE_SDIO:
- + offset += current_coreidx * SSB_CORE_SIZE;
- + return ssb_sdio_scan_read32(bus, offset);
- + }
- + printk("ssbread: %x\n", bus->mmio + offset);
- + return readl(bus->mmio + offset);
- +}
- +
- +static int scan_switchcore(struct ssb_bus *bus, u8 coreidx)
- +{
- + switch (bus->bustype) {
- + case SSB_BUSTYPE_SSB:
- + break;
- + case SSB_BUSTYPE_PCI:
- + return ssb_pci_switch_coreidx(bus, coreidx);
- + case SSB_BUSTYPE_PCMCIA:
- + return ssb_pcmcia_switch_coreidx(bus, coreidx);
- + case SSB_BUSTYPE_SDIO:
- + return ssb_sdio_scan_switch_coreidx(bus, coreidx);
- + }
- + return 0;
- +}
- +
- +void ssb_iounmap(struct ssb_bus *bus)
- +{
- + switch (bus->bustype) {
- + case SSB_BUSTYPE_SSB:
- + case SSB_BUSTYPE_PCMCIA:
- + iounmap(bus->mmio);
- + break;
- + case SSB_BUSTYPE_PCI:
- +#ifdef CONFIG_SSB_PCIHOST
- + pci_iounmap(bus->host_pci, bus->mmio);
- +#else
- + SSB_BUG_ON(1); /* Can't reach this code. */
- +#endif
- + break;
- + case SSB_BUSTYPE_SDIO:
- + break;
- + }
- + bus->mmio = NULL;
- + bus->mapped_device = NULL;
- +}
- +
- +static void __iomem *ssb_ioremap(struct ssb_bus *bus,
- + unsigned long baseaddr)
- +{
- + void __iomem *mmio = NULL;
- +
- + switch (bus->bustype) {
- + case SSB_BUSTYPE_SSB:
- + /* Only map the first core for now. */
- + /* fallthrough... */
- + case SSB_BUSTYPE_PCMCIA:
- + mmio = ioremap(baseaddr, SSB_CORE_SIZE);
- + break;
- + case SSB_BUSTYPE_PCI:
- +#ifdef CONFIG_SSB_PCIHOST
- + mmio = pci_iomap(bus->host_pci, 0, ~0UL);
- +#else
- + SSB_BUG_ON(1); /* Can't reach this code. */
- +#endif
- + break;
- + case SSB_BUSTYPE_SDIO:
- + /* Nothing to ioremap in the SDIO case, just fake it */
- + mmio = (void __iomem *)baseaddr;
- + break;
- + }
- +
- + return mmio;
- +}
- +
- +static int we_support_multiple_80211_cores(struct ssb_bus *bus)
- +{
- + /* More than one 802.11 core is only supported by special chips.
- + * There are chips with two 802.11 cores, but with dangling
- + * pins on the second core. Be careful and reject them here.
- + */
- +
- +#ifdef CONFIG_SSB_PCIHOST
- + if (bus->bustype == SSB_BUSTYPE_PCI) {
- + if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM &&
- + bus->host_pci->device == 0x4324)
- + return 1;
- + }
- +#endif /* CONFIG_SSB_PCIHOST */
- + return 0;
- +}
- +
- +int ssb_bus_scan1(struct ssb_bus *bus,
- + unsigned long baseaddr)
- +{
- + int err = -ENOMEM;
- + void __iomem *mmio;
- + u32 idhi, cc, rev, tmp;
- + int dev_i, i;
- + struct ssb_device *dev;
- + int nr_80211_cores = 0;
- +
- + mmio = ssb_ioremap(bus, baseaddr);
- + if (!mmio)
- + goto out;
- + bus->mmio = mmio;
- +printk("s1\n");
- + err = scan_switchcore(bus, 0); /* Switch to first core */
- + if (err)
- + goto err_unmap;
- +printk("s2\n");
- + tmp=scan_read32(bus, 0, 0);
- + printk("s2a: %x\n", tmp);
- + idhi = scan_read32(bus, 0, SSB_IDHIGH);
- + cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
- + rev = (idhi & SSB_IDHIGH_RCLO);
- + rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
- +printk("s3\n");
- + bus->nr_devices = 0;
- + if (cc == SSB_DEV_CHIPCOMMON) {
- + tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID);
- +printk("s4\n");
- + bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
- + bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >>
- + SSB_CHIPCO_REVSHIFT;
- + bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >>
- + SSB_CHIPCO_PACKSHIFT;
- + if (rev >= 4) {
- + bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >>
- + SSB_CHIPCO_NRCORESSHIFT;
- + }
- + tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP);
- + bus->chipco.capabilities = tmp;
- + } else {
- + printk("s5\n");
- + if (bus->bustype == SSB_BUSTYPE_PCI) {
- + bus->chip_id = pcidev_to_chipid(bus->host_pci);
- + pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
- + &bus->chip_rev);
- + bus->chip_package = 0;
- + } else {
- + bus->chip_id = 0x4710;
- + bus->chip_rev = 0;
- + bus->chip_package = 0;
- + }
- + }
- + printk("s6\n");
- + if (!bus->nr_devices)
- + bus->nr_devices = chipid_to_nrcores(bus->chip_id);
- + if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
- + ssb_printk(KERN_ERR PFX
- + "More than %d ssb cores found (%d)\n",
- + SSB_MAX_NR_CORES, bus->nr_devices);
- + goto err_unmap;
- + }
- + if (bus->bustype == SSB_BUSTYPE_SSB) {
- + printk("s7\n");
- + /* Now that we know the number of cores,
- + * remap the whole IO space for all cores.
- + */
- + err = -ENOMEM;
- + iounmap(mmio);
- + mmio = ioremap(baseaddr, SSB_CORE_SIZE * bus->nr_devices);
- + if (!mmio)
- + goto out;
- + bus->mmio = mmio;
- + }
- +
- + /* Fetch basic information about each core/device */
- + for (i = 0, dev_i = 0; i < bus->nr_devices; i++) {
- + printk("s8: %i\n", i);
- + err = scan_switchcore(bus, i);
- + if (err)
- + goto err_unmap;
- + dev = &(bus->devices[dev_i]);
- +printk("s9\n");
- + idhi = scan_read32(bus, i, SSB_IDHIGH);
- + dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
- + dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
- + dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
- + dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
- + dev->core_index = i;
- + dev->bus = bus;
- + dev->ops = bus->ops;
- +
- + ssb_printk(KERN_INFO PFX
- + "Core %d found: %s "
- + "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",
- + i, ssb_core_name(dev->id.coreid),
- + dev->id.coreid, dev->id.revision, dev->id.vendor);
- +
- + switch (dev->id.coreid) {
- + case SSB_DEV_80211:
- + nr_80211_cores++;
- + if (nr_80211_cores > 1) {
- + if (!we_support_multiple_80211_cores(bus)) {
- + ssb_dprintk(KERN_INFO PFX "Ignoring additional "
- + "802.11 core\n");
- + continue;
- + }
- + }
- + break;
- + case SSB_DEV_EXTIF:
- +#ifdef CONFIG_SSB_DRIVER_EXTIF
- + if (bus->extif.dev) {
- + ssb_printk(KERN_WARNING PFX
- + "WARNING: Multiple EXTIFs found\n");
- + break;
- + }
- + bus->extif.dev = dev;
- +#endif /* CONFIG_SSB_DRIVER_EXTIF */
- + break;
- + case SSB_DEV_CHIPCOMMON:
- + if (bus->chipco.dev) {
- + ssb_printk(KERN_WARNING PFX
- + "WARNING: Multiple ChipCommon found\n");
- + break;
- + }
- + bus->chipco.dev = dev;
- + break;
- + case SSB_DEV_MIPS:
- + case SSB_DEV_MIPS_3302:
- +#ifdef CONFIG_SSB_DRIVER_MIPS
- + if (bus->mipscore.dev) {
- + ssb_printk(KERN_WARNING PFX
- + "WARNING: Multiple MIPS cores found\n");
- + break;
- + }
- + bus->mipscore.dev = dev;
- + printk("bus->mipscore.dev: %x\n",bus->mipscore.dev);
- +#endif /* CONFIG_SSB_DRIVER_MIPS */
- + break;
- + case SSB_DEV_PCI:
- + case SSB_DEV_PCIE:
- +#ifdef CONFIG_SSB_DRIVER_PCICORE
- + if (bus->bustype == SSB_BUSTYPE_PCI) {
- + /* Ignore PCI cores on PCI-E cards.
- + * Ignore PCI-E cores on PCI cards. */
- + if (dev->id.coreid == SSB_DEV_PCI) {
- + if (bus->host_pci->is_pcie)
- + continue;
- + } else {
- + if (!bus->host_pci->is_pcie)
- + continue;
- + }
- + }
- + if (bus->pcicore.dev) {
- + ssb_printk(KERN_WARNING PFX
- + "WARNING: Multiple PCI(E) cores found\n");
- + break;
- + }
- + bus->pcicore.dev = dev;
- +#endif /* CONFIG_SSB_DRIVER_PCICORE */
- + break;
- + default:
- + break;
- + }
- +
- + dev_i++;
- + printk("s10\n");
- + }
- + bus->nr_devices = dev_i;
- +
- + err = 0;
- +out:
- + return err;
- +err_unmap:
- + ssb_iounmap(bus);
- + goto out;
- +}
- +
- +typedef u32 uint32;
- +
- +typedef volatile struct {
- + uint32 chipid; /* 0x0 */
- + uint32 capabilities;
- + uint32 corecontrol; /* corerev >= 1 */
- + uint32 bist;
- +
- + /* OTP */
- + uint32 otpstatus; /* 0x10, corerev >= 10 */
- + uint32 otpcontrol;
- + uint32 otpprog;
- + uint32 PAD1;
- +
- + /* Interrupt control */
- + uint32 intstatus; /* 0x20 */
- + uint32 intmask;
- + uint32 chipcontrol; /* 0x28, rev >= 11 */
- + uint32 chipstatus; /* 0x2c, rev >= 11 */
- +
- + /* Jtag Master */
- + uint32 jtagcmd; /* 0x30, rev >= 10 */
- + uint32 jtagir;
- + uint32 jtagdr;
- + uint32 jtagctrl;
- +
- + /* serial flash interface registers */
- + uint32 flashcontrol; /* 0x40 */
- + uint32 flashaddress;
- + uint32 flashdata;
- + uint32 PAD2[1];
- +
- + /* Silicon backplane configuration broadcast control */
- + uint32 broadcastaddress; /* 0x50 */
- + uint32 broadcastdata;
- +
- + /* gpio - cleared only by power-on-reset */
- + uint32 gpiopullup; /* 0x58, corerev >= 20 */
- + uint32 gpiopulldown; /* 0x5c, corerev >= 20 */
- + uint32 gpioin; /* 0x60 */
- + uint32 gpioout;
- + uint32 gpioouten;
- + uint32 gpiocontrol;
- + uint32 gpiointpolarity;
- + uint32 gpiointmask;
- +
- + /* GPIO events corerev >= 11 */
- + uint32 gpioevent;
- + uint32 gpioeventintmask;
- +
- + /* Watchdog timer */
- + uint32 watchdog; /* 0x80 */
- +
- + /* GPIO events corerev >= 11 */
- + uint32 gpioeventintpolarity;
- +
- + /* GPIO based LED powersave registers corerev >= 16 */
- + uint32 gpiotimerval; /* 0x88 */
- + uint32 gpiotimeroutmask;
- +
- + /* clock control */
- + uint32 clockcontrol_n; /* 0x90 */
- + uint32 clockcontrol_sb; /* aka m0 */
- + uint32 clockcontrol_pci; /* aka m1 */
- + uint32 clockcontrol_m2; /* mii/uart/mipsref */
- + uint32 clockcontrol_m3; /* cpu */
- + uint32 clkdiv; /* corerev >= 3 */
- + uint32 PAD3[2];
- +
- + /* pll delay registers (corerev >= 4) */
- + uint32 pll_on_delay; /* 0xb0 */
- + uint32 fref_sel_delay;
- + uint32 slow_clk_ctl; /* 5 < corerev < 10 */
- + uint32 PAD4[1];
- +
- + /* Instaclock registers (corerev >= 10) */
- + uint32 system_clk_ctl; /* 0xc0 */
- + uint32 clkstatestretch;
- + uint32 PAD5[13];
- +
- + /* In AI chips, pointer to erom */
- + uint32 eromptr;
- +} chipcregs_t;
- +
- +#define ER_VALID 1
- +#define ER_END 0xe
- +
- +static uint32
- +get_erom_ent(struct ssb_bus *bus, uint32 *eromptr, uint32 mask, uint32 match)
- +{
- + uint32 ent;
- + uint inv = 0, nom = 0;
- +
- + while (1) {
- + ent = readl(*eromptr);
- + *eromptr += sizeof(uint32);
- +
- + if (mask == 0)
- + break;
- +
- + if ((ent & ER_VALID) == 0) {
- + inv++;
- + continue;
- + }
- +
- + if (ent == (ER_END | ER_VALID))
- + break;
- +
- + if ((ent & mask) == match)
- + break;
- +
- + nom++;
- + }
- +
- + /*SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent));
- + if (inv + nom) {
- + SI_VMSG((" after %d invalid and %d non-matching entries\n", inv, nom));
- + }*/
- + return ent;
- +}
- +#define ER_ADD 4
- +#define ER_TAG1 0x6
- +#define AD_SP_MASK 0x00000f00
- +#define AD_SP_SHIFT 8
- +#define AD_ST_MASK 0x000000c0
- +#define AD_ADDR_MASK 0xfffff000
- +#define AD_AG32 0x0000000
- +#define AD_SZ_MASK 0x00000030
- +#define AD_SZ_SZD 0x00000030
- +#define SD_SZ_MASK 0xfffff000
- +#define SD_SG32 0x00000008
- +#define AD_SZ_SHIFT 4
- +#define AD_SZ_BASE 0x00001000
- +static uint32
- +get_asd(struct ssb_bus *bus, uint32 *eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh,
- + uint32 *sizel, uint32 *sizeh)
- +{
- + uint32 asd, sz, szd;
- +
- + asd = get_erom_ent(bus, eromptr, ER_VALID, ER_VALID);
- + if (((asd & ER_TAG1) != ER_ADD) ||
- + (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) ||
- + ((asd & AD_ST_MASK) != st)) {
- + /* This is not what we want, "push" it back */
- + *eromptr -= sizeof(uint32);
- + return 0;
- + }
- + *addrl = asd & AD_ADDR_MASK;
- + if (asd & AD_AG32)
- + *addrh = get_erom_ent(bus, eromptr, 0, 0);
- + else
- + *addrh = 0;
- + *sizeh = 0;
- + sz = asd & AD_SZ_MASK;
- + if (sz == AD_SZ_SZD) {
- + szd = get_erom_ent(bus, eromptr, 0, 0);
- + *sizel = szd & SD_SZ_MASK;
- + if (szd & SD_SG32)
- + *sizeh = get_erom_ent(bus, eromptr, 0, 0);
- + } else
- + *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
- +
- + printk(" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
- + sp, ad, st, *sizeh, *sizel, *addrh, *addrl);
- +
- + return asd;
- +}
- +
- +int ssb_bus_scan(struct ssb_bus *bus,
- + unsigned long baseaddr)
- +{
- + chipcregs_t *cc = (chipcregs_t *)baseaddr;
- + uint32 erombase, eromptr, eromlim;
- +
- + erombase = readl(KSEG1ADDR(&cc->eromptr));
- +#define SI_CORE_SIZE 0x1000
- +#define ER_TAG 0xe
- +#define ER_CI 0
- +
- + eromptr = (u32)ioremap(erombase, SI_CORE_SIZE);
- +
- + eromlim = eromptr + SI_CORE_SIZE;
- +
- + bus->nr_devices = 0;
- +
- + printk("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%08x, eromlim = 0x%08x\n",
- + baseaddr, erombase, eromptr, eromlim);
- + while (eromptr < eromlim) {
- + uint32 cia, cib, base, cid, mfg, crev, nmw, nsw, nmp, nsp;
- + uint32 mpd, asd, addrl, addrh, sizel, sizeh;
- + uint i, j, idx;
- + bool br;
- + struct ssb_device *dev = &(bus->devices[bus->nr_devices]);
- + br = 0;
- +
- + /* Grok a component */
- + cia = get_erom_ent(bus, &eromptr, ER_TAG, ER_CI);
- + if (cia == (ER_END | ER_VALID)) {
- + printk("Found END of erom after %d cores\n", bus->nr_devices);
- + return 0;
- + }
- + base = eromptr - sizeof(uint32);
- + cib = get_erom_ent(bus, &eromptr, 0, 0);
- +#define CIA_CID_MASK 0x000fff00
- +#define CIA_CID_SHIFT 8
- +#define CIA_MFG_MASK 0xfff00000
- +#define CIA_MFG_SHIFT 20
- +#define CIB_REV_MASK 0xff000000
- +#define CIB_REV_SHIFT 24
- +#define CIB_NMW_MASK 0x0007c000
- +#define CIB_NMW_SHIFT 14
- +#define CIB_NSW_SHIFT 19
- +#define CIB_NSW_MASK 0x00f80000
- +#define CIB_NMP_MASK 0x000001f0
- +#define CIB_NMP_SHIFT 4
- +#define CIB_NSP_SHIFT 9
- +#define CIB_NSP_MASK 0x00003e00
- +#define MFGID_ARM 0x43b
- +#define DEF_AI_COMP 0xfff
- +#define ER_MP 2
- +#define MPD_MP_MASK 0x000000f0
- +#define MPD_MP_SHIFT 4
- +#define MPD_MUI_MASK 0x0000ff00
- +#define MPD_MUI_SHIFT 8
- +#define AD_ST_SLAVE 0x00000000
- +#define AD_ST_BRIDGE 0x00000040
- +
- + if ((cib & ER_TAG) != ER_CI) {
- + printk("CIA not followed by CIB\n");
- + goto error;
- + }
- +
- + cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT;
- + mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
- + crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
- + nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT;
- + nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT;
- + nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
- + nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
- +
- + dev->id.coreid = cid;
- + dev->id.revision = crev;
- + dev->id.vendor = mfg;
- + dev->core_index = bus->nr_devices;
- + dev->bus = bus;
- + dev->ops = bus->ops;
- +
- + ssb_printk(KERN_INFO PFX
- + "Core %d found: %s "
- + "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",
- + bus->nr_devices, ssb_core_name(dev->id.coreid),
- + dev->id.coreid, dev->id.revision, dev->id.vendor);
- +
- + printk("Found component 0x%04x/0x%04x rev %d at erom addr 0x%08x, with nmw = %d, "
- + "nsw = %d, nmp = %d & nsp = %d\n",
- + mfg, cid, crev, base, nmw, nsw, nmp, nsp);
- +
- + if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) ||
- + (nmw + nsw == 0) || (nsp == 0)) {
- + printk("A component which is not a core\n");
- + continue;
- + }
- +
- +
- + for (i = 0; i < nmp; i++) {
- + mpd = get_erom_ent(bus, &eromptr, ER_VALID, ER_VALID);
- + if ((mpd & ER_TAG) != ER_MP) {
- + printk("Not enough MP entries for component 0x%x\n", cid);
- + goto error;
- + }
- + printk(" Master port %d, mp: %d id: %d\n", i,
- + (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT,
- + (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT);
- + }
- +#define AD_ST_MWRAP 0x000000c0
- +#define AD_ST_SWRAP 0x00000080
- + /* First Slave Address Descriptor should be port 0:
- + * the main register space for the core
- + */
- + asd = get_asd(bus, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
- + if (asd == 0) {
- + /* Try again to see if it is a bridge */
- + asd = get_asd(bus, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
- + &sizel, &sizeh);
- + if (asd != 0)
- + br = true;
- + else
- + if ((addrh != 0) || (sizeh != 0) || (sizel != SI_CORE_SIZE)) {
- + printk("First Slave ASD for core 0x%04x malformed "
- + "(0x%08x)\n", cid, asd);
- + goto error;
- + }
- + }
- + /* Get any more ASDs in port 0 */
- + j = 1;
- + do {
- + asd = get_asd(bus, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
- + &sizel, &sizeh);
- + if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE))
- + j++;
- + } while (asd != 0);
- +
- + /* Go through the ASDs for other slave ports */
- + for (i = 1; i < nsp; i++) {
- + j = 0;
- + do {
- + asd = get_asd(bus, &eromptr, i, j++, AD_ST_SLAVE, &addrl, &addrh,
- + &sizel, &sizeh);
- + } while (asd != 0);
- + if (j == 0) {
- + printk(" SP %d has no address descriptors\n", i);
- + goto error;
- + }
- + }
- +
- + /* Now get master wrappers */
- + for (i = 0; i < nmw; i++) {
- + asd = get_asd(bus, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh,
- + &sizel, &sizeh);
- + if (asd == 0) {
- + printk("Missing descriptor for MW %d\n", i);
- + goto error;
- + }
- + if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
- + printk("Master wrapper %d is not 4KB\n", i);
- + goto error;
- + }
- + }
- +
- + /* And finally slave wrappers */
- + for (i = 0; i < nsw; i++) {
- + uint fwp = (nsp == 1) ? 0 : 1;
- + asd = get_asd(bus, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh,
- + &sizel, &sizeh);
- + if (asd == 0) {
- + printk("Missing descriptor for SW %d\n", i);
- + goto error;
- + }
- + if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
- + printk("Slave wrapper %d is not 4KB\n", i);
- + goto error;
- + }
- + }
- +
- + /* Don't record bridges */
- + if (br)
- + continue;
- +
- + /* Done with core */
- + bus->nr_devices++;
- + }
- +
- + printk("Reached end of erom without finding END");
- +
- +error:
- + bus->nr_devices = 0;
- + return -1;
- +}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement