0001
0002
0003
0004
0005
0006
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
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
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
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
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
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
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
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
0228 switch (ci->id) {
0229
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
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");