linux/drivers/ssb/driver_pcicore.c
<<
>>
Prefs
   1/*
   2 * Sonics Silicon Backplane
   3 * Broadcom PCI-core driver
   4 *
   5 * Copyright 2005, Broadcom Corporation
   6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
   7 *
   8 * Licensed under the GNU/GPL. See COPYING for details.
   9 */
  10
  11#include "ssb_private.h"
  12
  13#include <linux/ssb/ssb.h>
  14#include <linux/pci.h>
  15#include <linux/export.h>
  16#include <linux/delay.h>
  17#include <linux/ssb/ssb_embedded.h>
  18
  19static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address);
  20static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data);
  21static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address);
  22static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
  23                                u8 address, u16 data);
  24
  25static inline
  26u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset)
  27{
  28        return ssb_read32(pc->dev, offset);
  29}
  30
  31static inline
  32void pcicore_write32(struct ssb_pcicore *pc, u16 offset, u32 value)
  33{
  34        ssb_write32(pc->dev, offset, value);
  35}
  36
  37static inline
  38u16 pcicore_read16(struct ssb_pcicore *pc, u16 offset)
  39{
  40        return ssb_read16(pc->dev, offset);
  41}
  42
  43static inline
  44void pcicore_write16(struct ssb_pcicore *pc, u16 offset, u16 value)
  45{
  46        ssb_write16(pc->dev, offset, value);
  47}
  48
  49/**************************************************
  50 * Code for hostmode operation.
  51 **************************************************/
  52
  53#ifdef CONFIG_SSB_PCICORE_HOSTMODE
  54
  55#include <asm/paccess.h>
  56/* Probe a 32bit value on the bus and catch bus exceptions.
  57 * Returns nonzero on a bus exception.
  58 * This is MIPS specific
  59 */
  60#define mips_busprobe32(val, addr)      get_dbe((val), ((u32 *)(addr)))
  61
  62/* Assume one-hot slot wiring */
  63#define SSB_PCI_SLOT_MAX        16
  64
  65/* Global lock is OK, as we won't have more than one extpci anyway. */
  66static DEFINE_SPINLOCK(cfgspace_lock);
  67/* Core to access the external PCI config space. Can only have one. */
  68static struct ssb_pcicore *extpci_core;
  69
  70
  71static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
  72                             unsigned int bus, unsigned int dev,
  73                             unsigned int func, unsigned int off)
  74{
  75        u32 addr = 0;
  76        u32 tmp;
  77
  78        /* We do only have one cardbus device behind the bridge. */
  79        if (pc->cardbusmode && (dev > 1))
  80                goto out;
  81
  82        if (bus == 0) {
  83                /* Type 0 transaction */
  84                if (unlikely(dev >= SSB_PCI_SLOT_MAX))
  85                        goto out;
  86                /* Slide the window */
  87                tmp = SSB_PCICORE_SBTOPCI_CFG0;
  88                tmp |= ((1 << (dev + 16)) & SSB_PCICORE_SBTOPCI1_MASK);
  89                pcicore_write32(pc, SSB_PCICORE_SBTOPCI1, tmp);
  90                /* Calculate the address */
  91                addr = SSB_PCI_CFG;
  92                addr |= ((1 << (dev + 16)) & ~SSB_PCICORE_SBTOPCI1_MASK);
  93                addr |= (func << 8);
  94                addr |= (off & ~3);
  95        } else {
  96                /* Type 1 transaction */
  97                pcicore_write32(pc, SSB_PCICORE_SBTOPCI1,
  98                                SSB_PCICORE_SBTOPCI_CFG1);
  99                /* Calculate the address */
 100                addr = SSB_PCI_CFG;
 101                addr |= (bus << 16);
 102                addr |= (dev << 11);
 103                addr |= (func << 8);
 104                addr |= (off & ~3);
 105        }
 106out:
 107        return addr;
 108}
 109
 110static int ssb_extpci_read_config(struct ssb_pcicore *pc,
 111                                  unsigned int bus, unsigned int dev,
 112                                  unsigned int func, unsigned int off,
 113                                  void *buf, int len)
 114{
 115        int err = -EINVAL;
 116        u32 addr, val;
 117        void __iomem *mmio;
 118
 119        WARN_ON(!pc->hostmode);
 120        if (unlikely(len != 1 && len != 2 && len != 4))
 121                goto out;
 122        addr = get_cfgspace_addr(pc, bus, dev, func, off);
 123        if (unlikely(!addr))
 124                goto out;
 125        err = -ENOMEM;
 126        mmio = ioremap(addr, len);
 127        if (!mmio)
 128                goto out;
 129
 130        if (mips_busprobe32(val, mmio)) {
 131                val = 0xffffffff;
 132                goto unmap;
 133        }
 134
 135        val = readl(mmio);
 136        val >>= (8 * (off & 3));
 137
 138        switch (len) {
 139        case 1:
 140                *((u8 *)buf) = (u8)val;
 141                break;
 142        case 2:
 143                *((u16 *)buf) = (u16)val;
 144                break;
 145        case 4:
 146                *((u32 *)buf) = (u32)val;
 147                break;
 148        }
 149        err = 0;
 150unmap:
 151        iounmap(mmio);
 152out:
 153        return err;
 154}
 155
 156static int ssb_extpci_write_config(struct ssb_pcicore *pc,
 157                                   unsigned int bus, unsigned int dev,
 158                                   unsigned int func, unsigned int off,
 159                                   const void *buf, int len)
 160{
 161        int err = -EINVAL;
 162        u32 addr, val = 0;
 163        void __iomem *mmio;
 164
 165        WARN_ON(!pc->hostmode);
 166        if (unlikely(len != 1 && len != 2 && len != 4))
 167                goto out;
 168        addr = get_cfgspace_addr(pc, bus, dev, func, off);
 169        if (unlikely(!addr))
 170                goto out;
 171        err = -ENOMEM;
 172        mmio = ioremap(addr, len);
 173        if (!mmio)
 174                goto out;
 175
 176        if (mips_busprobe32(val, mmio)) {
 177                val = 0xffffffff;
 178                goto unmap;
 179        }
 180
 181        switch (len) {
 182        case 1:
 183                val = readl(mmio);
 184                val &= ~(0xFF << (8 * (off & 3)));
 185                val |= *((const u8 *)buf) << (8 * (off & 3));
 186                break;
 187        case 2:
 188                val = readl(mmio);
 189                val &= ~(0xFFFF << (8 * (off & 3)));
 190                val |= *((const u16 *)buf) << (8 * (off & 3));
 191                break;
 192        case 4:
 193                val = *((const u32 *)buf);
 194                break;
 195        }
 196        writel(val, mmio);
 197
 198        err = 0;
 199unmap:
 200        iounmap(mmio);
 201out:
 202        return err;
 203}
 204
 205static int ssb_pcicore_read_config(struct pci_bus *bus, unsigned int devfn,
 206                                   int reg, int size, u32 *val)
 207{
 208        unsigned long flags;
 209        int err;
 210
 211        spin_lock_irqsave(&cfgspace_lock, flags);
 212        err = ssb_extpci_read_config(extpci_core, bus->number, PCI_SLOT(devfn),
 213                                     PCI_FUNC(devfn), reg, val, size);
 214        spin_unlock_irqrestore(&cfgspace_lock, flags);
 215
 216        return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
 217}
 218
 219static int ssb_pcicore_write_config(struct pci_bus *bus, unsigned int devfn,
 220                                    int reg, int size, u32 val)
 221{
 222        unsigned long flags;
 223        int err;
 224
 225        spin_lock_irqsave(&cfgspace_lock, flags);
 226        err = ssb_extpci_write_config(extpci_core, bus->number, PCI_SLOT(devfn),
 227                                      PCI_FUNC(devfn), reg, &val, size);
 228        spin_unlock_irqrestore(&cfgspace_lock, flags);
 229
 230        return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
 231}
 232
 233static struct pci_ops ssb_pcicore_pciops = {
 234        .read   = ssb_pcicore_read_config,
 235        .write  = ssb_pcicore_write_config,
 236};
 237
 238static struct resource ssb_pcicore_mem_resource = {
 239        .name   = "SSB PCIcore external memory",
 240        .start  = SSB_PCI_DMA,
 241        .end    = SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1,
 242        .flags  = IORESOURCE_MEM | IORESOURCE_PCI_FIXED,
 243};
 244
 245static struct resource ssb_pcicore_io_resource = {
 246        .name   = "SSB PCIcore external I/O",
 247        .start  = 0x100,
 248        .end    = 0x7FF,
 249        .flags  = IORESOURCE_IO | IORESOURCE_PCI_FIXED,
 250};
 251
 252static struct pci_controller ssb_pcicore_controller = {
 253        .pci_ops        = &ssb_pcicore_pciops,
 254        .io_resource    = &ssb_pcicore_io_resource,
 255        .mem_resource   = &ssb_pcicore_mem_resource,
 256};
 257
 258/* This function is called when doing a pci_enable_device().
 259 * We must first check if the device is a device on the PCI-core bridge.
 260 */
 261int ssb_pcicore_plat_dev_init(struct pci_dev *d)
 262{
 263        if (d->bus->ops != &ssb_pcicore_pciops) {
 264                /* This is not a device on the PCI-core bridge. */
 265                return -ENODEV;
 266        }
 267
 268        dev_info(&d->dev, "PCI: Fixing up device %s\n", pci_name(d));
 269
 270        /* Fix up interrupt lines */
 271        d->irq = ssb_mips_irq(extpci_core->dev) + 2;
 272        pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
 273
 274        return 0;
 275}
 276
 277/* Early PCI fixup for a device on the PCI-core bridge. */
 278static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
 279{
 280        u8 lat;
 281
 282        if (dev->bus->ops != &ssb_pcicore_pciops) {
 283                /* This is not a device on the PCI-core bridge. */
 284                return;
 285        }
 286        if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
 287                return;
 288
 289        dev_info(&dev->dev, "PCI: Fixing up bridge %s\n", pci_name(dev));
 290
 291        /* Enable PCI bridge bus mastering and memory space */
 292        pci_set_master(dev);
 293        if (pcibios_enable_device(dev, ~0) < 0) {
 294                dev_err(&dev->dev, "PCI: SSB bridge enable failed\n");
 295                return;
 296        }
 297
 298        /* Enable PCI bridge BAR1 prefetch and burst */
 299        pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
 300
 301        /* Make sure our latency is high enough to handle the devices behind us */
 302        lat = 168;
 303        dev_info(&dev->dev,
 304                 "PCI: Fixing latency timer of device %s to %u\n",
 305                 pci_name(dev), lat);
 306        pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 307}
 308DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge);
 309
 310/* PCI device IRQ mapping. */
 311int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 312{
 313        if (dev->bus->ops != &ssb_pcicore_pciops) {
 314                /* This is not a device on the PCI-core bridge. */
 315                return -ENODEV;
 316        }
 317        return ssb_mips_irq(extpci_core->dev) + 2;
 318}
 319
 320static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 321{
 322        u32 val;
 323
 324        if (WARN_ON(extpci_core))
 325                return;
 326        extpci_core = pc;
 327
 328        dev_dbg(pc->dev->dev, "PCIcore in host mode found\n");
 329        /* Reset devices on the external PCI bus */
 330        val = SSB_PCICORE_CTL_RST_OE;
 331        val |= SSB_PCICORE_CTL_CLK_OE;
 332        pcicore_write32(pc, SSB_PCICORE_CTL, val);
 333        val |= SSB_PCICORE_CTL_CLK; /* Clock on */
 334        pcicore_write32(pc, SSB_PCICORE_CTL, val);
 335        udelay(150); /* Assertion time demanded by the PCI standard */
 336        val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */
 337        pcicore_write32(pc, SSB_PCICORE_CTL, val);
 338        val = SSB_PCICORE_ARBCTL_INTERN;
 339        pcicore_write32(pc, SSB_PCICORE_ARBCTL, val);
 340        udelay(1); /* Assertion time demanded by the PCI standard */
 341
 342        if (pc->dev->bus->has_cardbus_slot) {
 343                dev_dbg(pc->dev->dev, "CardBus slot detected\n");
 344                pc->cardbusmode = 1;
 345                /* GPIO 1 resets the bridge */
 346                ssb_gpio_out(pc->dev->bus, 1, 1);
 347                ssb_gpio_outen(pc->dev->bus, 1, 1);
 348                pcicore_write16(pc, SSB_PCICORE_SPROM(0),
 349                                pcicore_read16(pc, SSB_PCICORE_SPROM(0))
 350                                | 0x0400);
 351        }
 352
 353        /* 64MB I/O window */
 354        pcicore_write32(pc, SSB_PCICORE_SBTOPCI0,
 355                        SSB_PCICORE_SBTOPCI_IO);
 356        /* 64MB config space */
 357        pcicore_write32(pc, SSB_PCICORE_SBTOPCI1,
 358                        SSB_PCICORE_SBTOPCI_CFG0);
 359        /* 1GB memory window */
 360        pcicore_write32(pc, SSB_PCICORE_SBTOPCI2,
 361                        SSB_PCICORE_SBTOPCI_MEM | SSB_PCI_DMA);
 362
 363        /*
 364         * Accessing PCI config without a proper delay after devices reset (not
 365         * GPIO reset) was causing reboots on WRT300N v1.0 (BCM4704).
 366         * Tested delay 850 us lowered reboot chance to 50-80%, 1000 us fixed it
 367         * completely. Flushing all writes was also tested but with no luck.
 368         * The same problem was reported for WRT350N v1 (BCM4705), so we just
 369         * sleep here unconditionally.
 370         */
 371        usleep_range(1000, 2000);
 372
 373        /* Enable PCI bridge BAR0 prefetch and burst */
 374        val = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
 375        ssb_extpci_write_config(pc, 0, 0, 0, PCI_COMMAND, &val, 2);
 376        /* Clear error conditions */
 377        val = 0;
 378        ssb_extpci_write_config(pc, 0, 0, 0, PCI_STATUS, &val, 2);
 379
 380        /* Enable PCI interrupts */
 381        pcicore_write32(pc, SSB_PCICORE_IMASK,
 382                        SSB_PCICORE_IMASK_INTA);
 383
 384        /* Ok, ready to run, register it to the system.
 385         * The following needs change, if we want to port hostmode
 386         * to non-MIPS platform.
 387         */
 388        ssb_pcicore_controller.io_map_base = (unsigned long)ioremap(SSB_PCI_MEM, 0x04000000);
 389        set_io_port_base(ssb_pcicore_controller.io_map_base);
 390        /* Give some time to the PCI controller to configure itself with the new
 391         * values. Not waiting at this point causes crashes of the machine.
 392         */
 393        mdelay(10);
 394        register_pci_controller(&ssb_pcicore_controller);
 395}
 396
 397static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
 398{
 399        struct ssb_bus *bus = pc->dev->bus;
 400        u16 chipid_top;
 401        u32 tmp;
 402
 403        chipid_top = (bus->chip_id & 0xFF00);
 404        if (chipid_top != 0x4700 &&
 405            chipid_top != 0x5300)
 406                return 0;
 407
 408        if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
 409                return 0;
 410
 411        /* The 200-pin BCM4712 package does not bond out PCI. Even when
 412         * PCI is bonded out, some boards may leave the pins floating.
 413         */
 414        if (bus->chip_id == 0x4712) {
 415                if (bus->chip_package == SSB_CHIPPACK_BCM4712S)
 416                        return 0;
 417                if (bus->chip_package == SSB_CHIPPACK_BCM4712M)
 418                        return 0;
 419        }
 420        if (bus->chip_id == 0x5350)
 421                return 0;
 422
 423        return !mips_busprobe32(tmp, (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE)));
 424}
 425#endif /* CONFIG_SSB_PCICORE_HOSTMODE */
 426
 427/**************************************************
 428 * Workarounds.
 429 **************************************************/
 430
 431static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
 432{
 433        u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0));
 434        if (((tmp & 0xF000) >> 12) != pc->dev->core_index) {
 435                tmp &= ~0xF000;
 436                tmp |= (pc->dev->core_index << 12);
 437                pcicore_write16(pc, SSB_PCICORE_SPROM(0), tmp);
 438        }
 439}
 440
 441static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc)
 442{
 443        return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
 444}
 445
 446static void ssb_pcicore_serdes_workaround(struct ssb_pcicore *pc)
 447{
 448        const u8 serdes_pll_device = 0x1D;
 449        const u8 serdes_rx_device = 0x1F;
 450        u16 tmp;
 451
 452        ssb_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */,
 453                            ssb_pcicore_polarity_workaround(pc));
 454        tmp = ssb_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */);
 455        if (tmp & 0x4000)
 456                ssb_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000);
 457}
 458
 459static void ssb_pcicore_pci_setup_workarounds(struct ssb_pcicore *pc)
 460{
 461        struct ssb_device *pdev = pc->dev;
 462        struct ssb_bus *bus = pdev->bus;
 463        u32 tmp;
 464
 465        tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2);
 466        tmp |= SSB_PCICORE_SBTOPCI_PREF;
 467        tmp |= SSB_PCICORE_SBTOPCI_BURST;
 468        pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp);
 469
 470        if (pdev->id.revision < 5) {
 471                tmp = ssb_read32(pdev, SSB_IMCFGLO);
 472                tmp &= ~SSB_IMCFGLO_SERTO;
 473                tmp |= 2;
 474                tmp &= ~SSB_IMCFGLO_REQTO;
 475                tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT;
 476                ssb_write32(pdev, SSB_IMCFGLO, tmp);
 477                ssb_commit_settings(bus);
 478        } else if (pdev->id.revision >= 11) {
 479                tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2);
 480                tmp |= SSB_PCICORE_SBTOPCI_MRM;
 481                pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp);
 482        }
 483}
 484
 485static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
 486{
 487        u32 tmp;
 488        u8 rev = pc->dev->id.revision;
 489
 490        if (rev == 0 || rev == 1) {
 491                /* TLP Workaround register. */
 492                tmp = ssb_pcie_read(pc, 0x4);
 493                tmp |= 0x8;
 494                ssb_pcie_write(pc, 0x4, tmp);
 495        }
 496        if (rev == 1) {
 497                /* DLLP Link Control register. */
 498                tmp = ssb_pcie_read(pc, 0x100);
 499                tmp |= 0x40;
 500                ssb_pcie_write(pc, 0x100, tmp);
 501        }
 502
 503        if (rev == 0) {
 504                const u8 serdes_rx_device = 0x1F;
 505
 506                ssb_pcie_mdio_write(pc, serdes_rx_device,
 507                                        2 /* Timer */, 0x8128);
 508                ssb_pcie_mdio_write(pc, serdes_rx_device,
 509                                        6 /* CDR */, 0x0100);
 510                ssb_pcie_mdio_write(pc, serdes_rx_device,
 511                                        7 /* CDR BW */, 0x1466);
 512        } else if (rev == 3 || rev == 4 || rev == 5) {
 513                /* TODO: DLLP Power Management Threshold */
 514                ssb_pcicore_serdes_workaround(pc);
 515                /* TODO: ASPM */
 516        } else if (rev == 7) {
 517                /* TODO: No PLL down */
 518        }
 519
 520        if (rev >= 6) {
 521                /* Miscellaneous Configuration Fixup */
 522                tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(5));
 523                if (!(tmp & 0x8000))
 524                        pcicore_write16(pc, SSB_PCICORE_SPROM(5),
 525                                        tmp | 0x8000);
 526        }
 527}
 528
 529/**************************************************
 530 * Generic and Clientmode operation code.
 531 **************************************************/
 532
 533static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
 534{
 535        struct ssb_device *pdev = pc->dev;
 536        struct ssb_bus *bus = pdev->bus;
 537
 538        if (bus->bustype == SSB_BUSTYPE_PCI)
 539                ssb_pcicore_fix_sprom_core_index(pc);
 540
 541        /* Disable PCI interrupts. */
 542        ssb_write32(pdev, SSB_INTVEC, 0);
 543
 544        /* Additional PCIe always once-executed workarounds */
 545        if (pc->dev->id.coreid == SSB_DEV_PCIE) {
 546                ssb_pcicore_serdes_workaround(pc);
 547                /* TODO: ASPM */
 548                /* TODO: Clock Request Update */
 549        }
 550}
 551
 552void ssb_pcicore_init(struct ssb_pcicore *pc)
 553{
 554        struct ssb_device *dev = pc->dev;
 555
 556        if (!dev)
 557                return;
 558        if (!ssb_device_is_enabled(dev))
 559                ssb_device_enable(dev, 0);
 560
 561#ifdef CONFIG_SSB_PCICORE_HOSTMODE
 562        pc->hostmode = pcicore_is_in_hostmode(pc);
 563        if (pc->hostmode)
 564                ssb_pcicore_init_hostmode(pc);
 565#endif /* CONFIG_SSB_PCICORE_HOSTMODE */
 566        if (!pc->hostmode)
 567                ssb_pcicore_init_clientmode(pc);
 568}
 569
 570static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address)
 571{
 572        pcicore_write32(pc, 0x130, address);
 573        return pcicore_read32(pc, 0x134);
 574}
 575
 576static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data)
 577{
 578        pcicore_write32(pc, 0x130, address);
 579        pcicore_write32(pc, 0x134, data);
 580}
 581
 582static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy)
 583{
 584        const u16 mdio_control = 0x128;
 585        const u16 mdio_data = 0x12C;
 586        u32 v;
 587        int i;
 588
 589        v = (1 << 30); /* Start of Transaction */
 590        v |= (1 << 28); /* Write Transaction */
 591        v |= (1 << 17); /* Turnaround */
 592        v |= (0x1F << 18);
 593        v |= (phy << 4);
 594        pcicore_write32(pc, mdio_data, v);
 595
 596        udelay(10);
 597        for (i = 0; i < 200; i++) {
 598                v = pcicore_read32(pc, mdio_control);
 599                if (v & 0x100 /* Trans complete */)
 600                        break;
 601                msleep(1);
 602        }
 603}
 604
 605static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address)
 606{
 607        const u16 mdio_control = 0x128;
 608        const u16 mdio_data = 0x12C;
 609        int max_retries = 10;
 610        u16 ret = 0;
 611        u32 v;
 612        int i;
 613
 614        v = 0x80; /* Enable Preamble Sequence */
 615        v |= 0x2; /* MDIO Clock Divisor */
 616        pcicore_write32(pc, mdio_control, v);
 617
 618        if (pc->dev->id.revision >= 10) {
 619                max_retries = 200;
 620                ssb_pcie_mdio_set_phy(pc, device);
 621        }
 622
 623        v = (1 << 30); /* Start of Transaction */
 624        v |= (1 << 29); /* Read Transaction */
 625        v |= (1 << 17); /* Turnaround */
 626        if (pc->dev->id.revision < 10)
 627                v |= (u32)device << 22;
 628        v |= (u32)address << 18;
 629        pcicore_write32(pc, mdio_data, v);
 630        /* Wait for the device to complete the transaction */
 631        udelay(10);
 632        for (i = 0; i < max_retries; i++) {
 633                v = pcicore_read32(pc, mdio_control);
 634                if (v & 0x100 /* Trans complete */) {
 635                        udelay(10);
 636                        ret = pcicore_read32(pc, mdio_data);
 637                        break;
 638                }
 639                msleep(1);
 640        }
 641        pcicore_write32(pc, mdio_control, 0);
 642        return ret;
 643}
 644
 645static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
 646                                u8 address, u16 data)
 647{
 648        const u16 mdio_control = 0x128;
 649        const u16 mdio_data = 0x12C;
 650        int max_retries = 10;
 651        u32 v;
 652        int i;
 653
 654        v = 0x80; /* Enable Preamble Sequence */
 655        v |= 0x2; /* MDIO Clock Divisor */
 656        pcicore_write32(pc, mdio_control, v);
 657
 658        if (pc->dev->id.revision >= 10) {
 659                max_retries = 200;
 660                ssb_pcie_mdio_set_phy(pc, device);
 661        }
 662
 663        v = (1 << 30); /* Start of Transaction */
 664        v |= (1 << 28); /* Write Transaction */
 665        v |= (1 << 17); /* Turnaround */
 666        if (pc->dev->id.revision < 10)
 667                v |= (u32)device << 22;
 668        v |= (u32)address << 18;
 669        v |= data;
 670        pcicore_write32(pc, mdio_data, v);
 671        /* Wait for the device to complete the transaction */
 672        udelay(10);
 673        for (i = 0; i < max_retries; i++) {
 674                v = pcicore_read32(pc, mdio_control);
 675                if (v & 0x100 /* Trans complete */)
 676                        break;
 677                msleep(1);
 678        }
 679        pcicore_write32(pc, mdio_control, 0);
 680}
 681
 682int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
 683                                   struct ssb_device *dev)
 684{
 685        struct ssb_device *pdev = pc->dev;
 686        struct ssb_bus *bus;
 687        int err = 0;
 688        u32 tmp;
 689
 690        if (dev->bus->bustype != SSB_BUSTYPE_PCI) {
 691                /* This SSB device is not on a PCI host-bus. So the IRQs are
 692                 * not routed through the PCI core.
 693                 * So we must not enable routing through the PCI core.
 694                 */
 695                goto out;
 696        }
 697
 698        if (!pdev)
 699                goto out;
 700        bus = pdev->bus;
 701
 702        might_sleep_if(pdev->id.coreid != SSB_DEV_PCI);
 703
 704        /* Enable interrupts for this device. */
 705        if ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE)) {
 706                u32 coremask;
 707
 708                /* Calculate the "coremask" for the device. */
 709                coremask = (1 << dev->core_index);
 710
 711                WARN_ON(bus->bustype != SSB_BUSTYPE_PCI);
 712                err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp);
 713                if (err)
 714                        goto out;
 715                tmp |= coremask << 8;
 716                err = pci_write_config_dword(bus->host_pci, SSB_PCI_IRQMASK, tmp);
 717                if (err)
 718                        goto out;
 719        } else {
 720                u32 intvec;
 721
 722                intvec = ssb_read32(pdev, SSB_INTVEC);
 723                tmp = ssb_read32(dev, SSB_TPSFLAG);
 724                tmp &= SSB_TPSFLAG_BPFLAG;
 725                intvec |= (1 << tmp);
 726                ssb_write32(pdev, SSB_INTVEC, intvec);
 727        }
 728
 729        /* Setup PCIcore operation. */
 730        if (pc->setup_done)
 731                goto out;
 732        if (pdev->id.coreid == SSB_DEV_PCI) {
 733                ssb_pcicore_pci_setup_workarounds(pc);
 734        } else {
 735                WARN_ON(pdev->id.coreid != SSB_DEV_PCIE);
 736                ssb_pcicore_pcie_setup_workarounds(pc);
 737        }
 738        pc->setup_done = 1;
 739out:
 740        return err;
 741}
 742EXPORT_SYMBOL(ssb_pcicore_dev_irqvecs_enable);
 743