root/drivers/ssb/scan.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ssb_core_name
  2. pcidev_to_chipid
  3. chipid_to_nrcores
  4. scan_read32
  5. scan_switchcore
  6. ssb_iounmap
  7. ssb_ioremap
  8. we_support_multiple_80211_cores
  9. ssb_bus_scan

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

/* [<][>][^][v][top][bottom][index][help] */