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