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