Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Driver for (BCM4706)? GBit MAC core on BCMA bus.
0003  *
0004  * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
0005  *
0006  * Licensed under the GNU/GPL. See COPYING for details.
0007  */
0008 
0009 #define pr_fmt(fmt)     KBUILD_MODNAME ": " fmt
0010 
0011 #include <linux/bcma/bcma.h>
0012 #include <linux/brcmphy.h>
0013 #include <linux/etherdevice.h>
0014 #include <linux/of_mdio.h>
0015 #include <linux/of_net.h>
0016 #include "bgmac.h"
0017 
0018 static inline bool bgmac_is_bcm4707_family(struct bcma_device *core)
0019 {
0020     switch (core->bus->chipinfo.id) {
0021     case BCMA_CHIP_ID_BCM4707:
0022     case BCMA_CHIP_ID_BCM47094:
0023     case BCMA_CHIP_ID_BCM53018:
0024         return true;
0025     default:
0026         return false;
0027     }
0028 }
0029 
0030 /**************************************************
0031  * BCMA bus ops
0032  **************************************************/
0033 
0034 static u32 bcma_bgmac_read(struct bgmac *bgmac, u16 offset)
0035 {
0036     return bcma_read32(bgmac->bcma.core, offset);
0037 }
0038 
0039 static void bcma_bgmac_write(struct bgmac *bgmac, u16 offset, u32 value)
0040 {
0041     bcma_write32(bgmac->bcma.core, offset, value);
0042 }
0043 
0044 static u32 bcma_bgmac_idm_read(struct bgmac *bgmac, u16 offset)
0045 {
0046     return bcma_aread32(bgmac->bcma.core, offset);
0047 }
0048 
0049 static void bcma_bgmac_idm_write(struct bgmac *bgmac, u16 offset, u32 value)
0050 {
0051     return bcma_awrite32(bgmac->bcma.core, offset, value);
0052 }
0053 
0054 static bool bcma_bgmac_clk_enabled(struct bgmac *bgmac)
0055 {
0056     return bcma_core_is_enabled(bgmac->bcma.core);
0057 }
0058 
0059 static void bcma_bgmac_clk_enable(struct bgmac *bgmac, u32 flags)
0060 {
0061     bcma_core_enable(bgmac->bcma.core, flags);
0062 }
0063 
0064 static void bcma_bgmac_cco_ctl_maskset(struct bgmac *bgmac, u32 offset,
0065                        u32 mask, u32 set)
0066 {
0067     struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc;
0068 
0069     bcma_chipco_chipctl_maskset(cc, offset, mask, set);
0070 }
0071 
0072 static u32 bcma_bgmac_get_bus_clock(struct bgmac *bgmac)
0073 {
0074     struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc;
0075 
0076     return bcma_pmu_get_bus_clock(cc);
0077 }
0078 
0079 static void bcma_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset, u32 mask,
0080                      u32 set)
0081 {
0082     bcma_maskset32(bgmac->bcma.cmn, offset, mask, set);
0083 }
0084 
0085 static int bcma_phy_connect(struct bgmac *bgmac)
0086 {
0087     struct phy_device *phy_dev;
0088     char bus_id[MII_BUS_ID_SIZE + 3];
0089 
0090     /* DT info should be the most accurate */
0091     phy_dev = of_phy_get_and_connect(bgmac->net_dev, bgmac->dev->of_node,
0092                      bgmac_adjust_link);
0093     if (phy_dev)
0094         return 0;
0095 
0096     /* Connect to the PHY */
0097     if (bgmac->mii_bus && bgmac->phyaddr != BGMAC_PHY_NOREGS) {
0098         snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
0099              bgmac->phyaddr);
0100         phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link,
0101                       PHY_INTERFACE_MODE_MII);
0102         if (IS_ERR(phy_dev)) {
0103             dev_err(bgmac->dev, "PHY connection failed\n");
0104             return PTR_ERR(phy_dev);
0105         }
0106 
0107         return 0;
0108     }
0109 
0110     /* Assume a fixed link to the switch port */
0111     return bgmac_phy_connect_direct(bgmac);
0112 }
0113 
0114 static const struct bcma_device_id bgmac_bcma_tbl[] = {
0115     BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT,
0116           BCMA_ANY_REV, BCMA_ANY_CLASS),
0117     BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_MAC_GBIT, BCMA_ANY_REV,
0118           BCMA_ANY_CLASS),
0119     {},
0120 };
0121 MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl);
0122 
0123 /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
0124 static int bgmac_probe(struct bcma_device *core)
0125 {
0126     struct bcma_chipinfo *ci = &core->bus->chipinfo;
0127     struct ssb_sprom *sprom = &core->bus->sprom;
0128     struct mii_bus *mii_bus;
0129     struct bgmac *bgmac;
0130     const u8 *mac;
0131     int err;
0132 
0133     bgmac = bgmac_alloc(&core->dev);
0134     if (!bgmac)
0135         return -ENOMEM;
0136 
0137     bgmac->bcma.core = core;
0138     bgmac->dma_dev = core->dma_dev;
0139     bgmac->irq = core->irq;
0140 
0141     bcma_set_drvdata(core, bgmac);
0142 
0143     err = of_get_ethdev_address(bgmac->dev->of_node, bgmac->net_dev);
0144     if (err == -EPROBE_DEFER)
0145         return err;
0146 
0147     /* If no MAC address assigned via device tree, check SPROM */
0148     if (err) {
0149         switch (core->core_unit) {
0150         case 0:
0151             mac = sprom->et0mac;
0152             break;
0153         case 1:
0154             mac = sprom->et1mac;
0155             break;
0156         case 2:
0157             mac = sprom->et2mac;
0158             break;
0159         default:
0160             dev_err(bgmac->dev, "Unsupported core_unit %d\n",
0161                 core->core_unit);
0162             err = -ENOTSUPP;
0163             goto err;
0164         }
0165         eth_hw_addr_set(bgmac->net_dev, mac);
0166     }
0167 
0168     /* On BCM4706 we need common core to access PHY */
0169     if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
0170         !core->bus->drv_gmac_cmn.core) {
0171         dev_err(bgmac->dev, "GMAC CMN core not found (required for BCM4706)\n");
0172         err = -ENODEV;
0173         goto err;
0174     }
0175     bgmac->bcma.cmn = core->bus->drv_gmac_cmn.core;
0176 
0177     switch (core->core_unit) {
0178     case 0:
0179         bgmac->phyaddr = sprom->et0phyaddr;
0180         break;
0181     case 1:
0182         bgmac->phyaddr = sprom->et1phyaddr;
0183         break;
0184     case 2:
0185         bgmac->phyaddr = sprom->et2phyaddr;
0186         break;
0187     }
0188     bgmac->phyaddr &= BGMAC_PHY_MASK;
0189     if (bgmac->phyaddr == BGMAC_PHY_MASK) {
0190         dev_err(bgmac->dev, "No PHY found\n");
0191         err = -ENODEV;
0192         goto err;
0193     }
0194     dev_info(bgmac->dev, "Found PHY addr: %d%s\n", bgmac->phyaddr,
0195          bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");
0196 
0197     if (!bgmac_is_bcm4707_family(core) &&
0198         !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) {
0199         struct phy_device *phydev;
0200 
0201         mii_bus = bcma_mdio_mii_register(bgmac);
0202         if (IS_ERR(mii_bus)) {
0203             err = PTR_ERR(mii_bus);
0204             goto err;
0205         }
0206         bgmac->mii_bus = mii_bus;
0207 
0208         phydev = mdiobus_get_phy(bgmac->mii_bus, bgmac->phyaddr);
0209         if (ci->id == BCMA_CHIP_ID_BCM53573 && phydev &&
0210             (phydev->drv->phy_id & phydev->drv->phy_id_mask) == PHY_ID_BCM54210E)
0211             phydev->dev_flags |= PHY_BRCM_EN_MASTER_MODE;
0212     }
0213 
0214     if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
0215         dev_err(bgmac->dev, "PCI setup not implemented\n");
0216         err = -ENOTSUPP;
0217         goto err1;
0218     }
0219 
0220     bgmac->has_robosw = !!(sprom->boardflags_lo & BGMAC_BFL_ENETROBO);
0221     if (bgmac->has_robosw)
0222         dev_warn(bgmac->dev, "Support for Roboswitch not implemented\n");
0223 
0224     if (sprom->boardflags_lo & BGMAC_BFL_ENETADM)
0225         dev_warn(bgmac->dev, "Support for ADMtek ethernet switch not implemented\n");
0226 
0227     /* Feature Flags */
0228     switch (ci->id) {
0229     /* BCM 471X/535X family */
0230     case BCMA_CHIP_ID_BCM4716:
0231         bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
0232         fallthrough;
0233     case BCMA_CHIP_ID_BCM47162:
0234         bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL2;
0235         bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
0236         break;
0237     case BCMA_CHIP_ID_BCM5357:
0238     case BCMA_CHIP_ID_BCM53572:
0239         bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
0240         bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
0241         bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
0242         bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
0243         if (ci->pkg == BCMA_PKG_ID_BCM47188 ||
0244             ci->pkg == BCMA_PKG_ID_BCM47186) {
0245             bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
0246             bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
0247         }
0248         if (ci->pkg == BCMA_PKG_ID_BCM5358)
0249             bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII;
0250         break;
0251     case BCMA_CHIP_ID_BCM53573:
0252         bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
0253         bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
0254         if (ci->pkg == BCMA_PKG_ID_BCM47189)
0255             bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
0256         if (core->core_unit == 0) {
0257             bgmac->feature_flags |= BGMAC_FEAT_CC4_IF_SW_TYPE;
0258             if (ci->pkg == BCMA_PKG_ID_BCM47189)
0259                 bgmac->feature_flags |=
0260                     BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII;
0261         } else if (core->core_unit == 1) {
0262             bgmac->feature_flags |= BGMAC_FEAT_IRQ_ID_OOB_6;
0263             bgmac->feature_flags |= BGMAC_FEAT_CC7_IF_TYPE_RGMII;
0264         }
0265         break;
0266     case BCMA_CHIP_ID_BCM4749:
0267         bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
0268         bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
0269         bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
0270         bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
0271         if (ci->pkg == 10) {
0272             bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
0273             bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
0274         }
0275         break;
0276     /* bcm4707_family */
0277     case BCMA_CHIP_ID_BCM4707:
0278     case BCMA_CHIP_ID_BCM47094:
0279     case BCMA_CHIP_ID_BCM53018:
0280         bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
0281         bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
0282         bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
0283         break;
0284     default:
0285         bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
0286         bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
0287     }
0288 
0289     if (!bgmac_is_bcm4707_family(core) && core->id.rev > 2)
0290         bgmac->feature_flags |= BGMAC_FEAT_MISC_PLL_REQ;
0291 
0292     if (core->id.id == BCMA_CORE_4706_MAC_GBIT) {
0293         bgmac->feature_flags |= BGMAC_FEAT_CMN_PHY_CTL;
0294         bgmac->feature_flags |= BGMAC_FEAT_NO_CLR_MIB;
0295     }
0296 
0297     if (core->id.rev >= 4) {
0298         bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
0299         bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
0300         bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
0301     }
0302 
0303     bgmac->read = bcma_bgmac_read;
0304     bgmac->write = bcma_bgmac_write;
0305     bgmac->idm_read = bcma_bgmac_idm_read;
0306     bgmac->idm_write = bcma_bgmac_idm_write;
0307     bgmac->clk_enabled = bcma_bgmac_clk_enabled;
0308     bgmac->clk_enable = bcma_bgmac_clk_enable;
0309     bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset;
0310     bgmac->get_bus_clock = bcma_bgmac_get_bus_clock;
0311     bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32;
0312     bgmac->phy_connect = bcma_phy_connect;
0313 
0314     err = bgmac_enet_probe(bgmac);
0315     if (err)
0316         goto err1;
0317 
0318     return 0;
0319 
0320 err1:
0321     bcma_mdio_mii_unregister(bgmac->mii_bus);
0322 err:
0323     bcma_set_drvdata(core, NULL);
0324 
0325     return err;
0326 }
0327 
0328 static void bgmac_remove(struct bcma_device *core)
0329 {
0330     struct bgmac *bgmac = bcma_get_drvdata(core);
0331 
0332     bcma_mdio_mii_unregister(bgmac->mii_bus);
0333     bgmac_enet_remove(bgmac);
0334     bcma_set_drvdata(core, NULL);
0335 }
0336 
0337 static struct bcma_driver bgmac_bcma_driver = {
0338     .name       = KBUILD_MODNAME,
0339     .id_table   = bgmac_bcma_tbl,
0340     .probe      = bgmac_probe,
0341     .remove     = bgmac_remove,
0342 };
0343 
0344 static int __init bgmac_init(void)
0345 {
0346     int err;
0347 
0348     err = bcma_driver_register(&bgmac_bcma_driver);
0349     if (err)
0350         return err;
0351     pr_info("Broadcom 47xx GBit MAC driver loaded\n");
0352 
0353     return 0;
0354 }
0355 
0356 static void __exit bgmac_exit(void)
0357 {
0358     bcma_driver_unregister(&bgmac_bcma_driver);
0359 }
0360 
0361 module_init(bgmac_init)
0362 module_exit(bgmac_exit)
0363 
0364 MODULE_AUTHOR("Rafał Miłecki");
0365 MODULE_LICENSE("GPL");