linux/drivers/ssb/driver_gige.c
<<
>>
Prefs
   1/*
   2 * Sonics Silicon Backplane
   3 * Broadcom Gigabit Ethernet core driver
   4 *
   5 * Copyright 2008, Broadcom Corporation
   6 * Copyright 2008, Michael Buesch <mb@bu3sch.de>
   7 *
   8 * Licensed under the GNU/GPL. See COPYING for details.
   9 */
  10
  11#include <linux/ssb/ssb.h>
  12#include <linux/ssb/ssb_driver_gige.h>
  13#include <linux/pci.h>
  14#include <linux/pci_regs.h>
  15
  16
  17/*
  18MODULE_DESCRIPTION("SSB Broadcom Gigabit Ethernet driver");
  19MODULE_AUTHOR("Michael Buesch");
  20MODULE_LICENSE("GPL");
  21*/
  22
  23static const struct ssb_device_id ssb_gige_tbl[] = {
  24        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV),
  25        SSB_DEVTABLE_END
  26};
  27/* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */
  28
  29
  30static inline u8 gige_read8(struct ssb_gige *dev, u16 offset)
  31{
  32        return ssb_read8(dev->dev, offset);
  33}
  34
  35static inline u16 gige_read16(struct ssb_gige *dev, u16 offset)
  36{
  37        return ssb_read16(dev->dev, offset);
  38}
  39
  40static inline u32 gige_read32(struct ssb_gige *dev, u16 offset)
  41{
  42        return ssb_read32(dev->dev, offset);
  43}
  44
  45static inline void gige_write8(struct ssb_gige *dev,
  46                               u16 offset, u8 value)
  47{
  48        ssb_write8(dev->dev, offset, value);
  49}
  50
  51static inline void gige_write16(struct ssb_gige *dev,
  52                                u16 offset, u16 value)
  53{
  54        ssb_write16(dev->dev, offset, value);
  55}
  56
  57static inline void gige_write32(struct ssb_gige *dev,
  58                                u16 offset, u32 value)
  59{
  60        ssb_write32(dev->dev, offset, value);
  61}
  62
  63static inline
  64u8 gige_pcicfg_read8(struct ssb_gige *dev, unsigned int offset)
  65{
  66        BUG_ON(offset >= 256);
  67        return gige_read8(dev, SSB_GIGE_PCICFG + offset);
  68}
  69
  70static inline
  71u16 gige_pcicfg_read16(struct ssb_gige *dev, unsigned int offset)
  72{
  73        BUG_ON(offset >= 256);
  74        return gige_read16(dev, SSB_GIGE_PCICFG + offset);
  75}
  76
  77static inline
  78u32 gige_pcicfg_read32(struct ssb_gige *dev, unsigned int offset)
  79{
  80        BUG_ON(offset >= 256);
  81        return gige_read32(dev, SSB_GIGE_PCICFG + offset);
  82}
  83
  84static inline
  85void gige_pcicfg_write8(struct ssb_gige *dev,
  86                        unsigned int offset, u8 value)
  87{
  88        BUG_ON(offset >= 256);
  89        gige_write8(dev, SSB_GIGE_PCICFG + offset, value);
  90}
  91
  92static inline
  93void gige_pcicfg_write16(struct ssb_gige *dev,
  94                         unsigned int offset, u16 value)
  95{
  96        BUG_ON(offset >= 256);
  97        gige_write16(dev, SSB_GIGE_PCICFG + offset, value);
  98}
  99
 100static inline
 101void gige_pcicfg_write32(struct ssb_gige *dev,
 102                         unsigned int offset, u32 value)
 103{
 104        BUG_ON(offset >= 256);
 105        gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
 106}
 107
 108static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
 109                                    int reg, int size, u32 *val)
 110{
 111        struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
 112        unsigned long flags;
 113
 114        if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
 115                return PCIBIOS_DEVICE_NOT_FOUND;
 116        if (reg >= 256)
 117                return PCIBIOS_DEVICE_NOT_FOUND;
 118
 119        spin_lock_irqsave(&dev->lock, flags);
 120        switch (size) {
 121        case 1:
 122                *val = gige_pcicfg_read8(dev, reg);
 123                break;
 124        case 2:
 125                *val = gige_pcicfg_read16(dev, reg);
 126                break;
 127        case 4:
 128                *val = gige_pcicfg_read32(dev, reg);
 129                break;
 130        default:
 131                WARN_ON(1);
 132        }
 133        spin_unlock_irqrestore(&dev->lock, flags);
 134
 135        return PCIBIOS_SUCCESSFUL;
 136}
 137
 138static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
 139                                     int reg, int size, u32 val)
 140{
 141        struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
 142        unsigned long flags;
 143
 144        if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
 145                return PCIBIOS_DEVICE_NOT_FOUND;
 146        if (reg >= 256)
 147                return PCIBIOS_DEVICE_NOT_FOUND;
 148
 149        spin_lock_irqsave(&dev->lock, flags);
 150        switch (size) {
 151        case 1:
 152                gige_pcicfg_write8(dev, reg, val);
 153                break;
 154        case 2:
 155                gige_pcicfg_write16(dev, reg, val);
 156                break;
 157        case 4:
 158                gige_pcicfg_write32(dev, reg, val);
 159                break;
 160        default:
 161                WARN_ON(1);
 162        }
 163        spin_unlock_irqrestore(&dev->lock, flags);
 164
 165        return PCIBIOS_SUCCESSFUL;
 166}
 167
 168static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
 169{
 170        struct ssb_gige *dev;
 171        u32 base, tmslow, tmshigh;
 172
 173        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 174        if (!dev)
 175                return -ENOMEM;
 176        dev->dev = sdev;
 177
 178        spin_lock_init(&dev->lock);
 179        dev->pci_controller.pci_ops = &dev->pci_ops;
 180        dev->pci_controller.io_resource = &dev->io_resource;
 181        dev->pci_controller.mem_resource = &dev->mem_resource;
 182        dev->pci_controller.io_map_base = 0x800;
 183        dev->pci_ops.read = ssb_gige_pci_read_config;
 184        dev->pci_ops.write = ssb_gige_pci_write_config;
 185
 186        dev->io_resource.name = SSB_GIGE_IO_RES_NAME;
 187        dev->io_resource.start = 0x800;
 188        dev->io_resource.end = 0x8FF;
 189        dev->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
 190
 191        if (!ssb_device_is_enabled(sdev))
 192                ssb_device_enable(sdev, 0);
 193
 194        /* Setup BAR0. This is a 64k MMIO region. */
 195        base = ssb_admatch_base(ssb_read32(sdev, SSB_ADMATCH1));
 196        gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_0, base);
 197        gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_1, 0);
 198
 199        dev->mem_resource.name = SSB_GIGE_MEM_RES_NAME;
 200        dev->mem_resource.start = base;
 201        dev->mem_resource.end = base + 0x10000 - 1;
 202        dev->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
 203
 204        /* Enable the memory region. */
 205        gige_pcicfg_write16(dev, PCI_COMMAND,
 206                            gige_pcicfg_read16(dev, PCI_COMMAND)
 207                            | PCI_COMMAND_MEMORY);
 208
 209        /* Write flushing is controlled by the Flush Status Control register.
 210         * We want to flush every register write with a timeout and we want
 211         * to disable the IRQ mask while flushing to avoid concurrency.
 212         * Note that automatic write flushing does _not_ work from
 213         * an IRQ handler. The driver must flush manually by reading a register.
 214         */
 215        gige_write32(dev, SSB_GIGE_SHIM_FLUSHSTAT, 0x00000068);
 216
 217        /* Check if we have an RGMII or GMII PHY-bus.
 218         * On RGMII do not bypass the DLLs */
 219        tmslow = ssb_read32(sdev, SSB_TMSLOW);
 220        tmshigh = ssb_read32(sdev, SSB_TMSHIGH);
 221        if (tmshigh & SSB_GIGE_TMSHIGH_RGMII) {
 222                tmslow &= ~SSB_GIGE_TMSLOW_TXBYPASS;
 223                tmslow &= ~SSB_GIGE_TMSLOW_RXBYPASS;
 224                dev->has_rgmii = 1;
 225        } else {
 226                tmslow |= SSB_GIGE_TMSLOW_TXBYPASS;
 227                tmslow |= SSB_GIGE_TMSLOW_RXBYPASS;
 228                dev->has_rgmii = 0;
 229        }
 230        tmslow |= SSB_GIGE_TMSLOW_DLLEN;
 231        ssb_write32(sdev, SSB_TMSLOW, tmslow);
 232
 233        ssb_set_drvdata(sdev, dev);
 234        register_pci_controller(&dev->pci_controller);
 235
 236        return 0;
 237}
 238
 239bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
 240{
 241        if (!pdev->resource[0].name)
 242                return 0;
 243        return (strcmp(pdev->resource[0].name, SSB_GIGE_MEM_RES_NAME) == 0);
 244}
 245EXPORT_SYMBOL(pdev_is_ssb_gige_core);
 246
 247int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
 248                                   struct pci_dev *pdev)
 249{
 250        struct ssb_gige *dev = ssb_get_drvdata(sdev);
 251        struct resource *res;
 252
 253        if (pdev->bus->ops != &dev->pci_ops) {
 254                /* The PCI device is not on this SSB GigE bridge device. */
 255                return -ENODEV;
 256        }
 257
 258        /* Fixup the PCI resources. */
 259        res = &(pdev->resource[0]);
 260        res->flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
 261        res->name = dev->mem_resource.name;
 262        res->start = dev->mem_resource.start;
 263        res->end = dev->mem_resource.end;
 264
 265        /* Fixup interrupt lines. */
 266        pdev->irq = ssb_mips_irq(sdev) + 2;
 267        pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
 268
 269        return 0;
 270}
 271
 272int ssb_gige_map_irq(struct ssb_device *sdev,
 273                     const struct pci_dev *pdev)
 274{
 275        struct ssb_gige *dev = ssb_get_drvdata(sdev);
 276
 277        if (pdev->bus->ops != &dev->pci_ops) {
 278                /* The PCI device is not on this SSB GigE bridge device. */
 279                return -ENODEV;
 280        }
 281
 282        return ssb_mips_irq(sdev) + 2;
 283}
 284
 285static struct ssb_driver ssb_gige_driver = {
 286        .name           = "BCM-GigE",
 287        .id_table       = ssb_gige_tbl,
 288        .probe          = ssb_gige_probe,
 289};
 290
 291int ssb_gige_init(void)
 292{
 293        return ssb_driver_register(&ssb_gige_driver);
 294}
 295