1 /* 2 * Driver for (BCM4706)? GBit MAC core on BCMA bus. 3 * 4 * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com> 5 * 6 * Licensed under the GNU/GPL. See COPYING for details. 7 */ 8 9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 11 #include <linux/bcma/bcma.h> 12 #include <linux/brcmphy.h> 13 #include <linux/etherdevice.h> 14 #include <linux/of_net.h> 15 #include "bgmac.h" 16 17 static inline bool bgmac_is_bcm4707_family(struct bcma_device *core) 18 { 19 switch (core->bus->chipinfo.id) { 20 case BCMA_CHIP_ID_BCM4707: 21 case BCMA_CHIP_ID_BCM47094: 22 case BCMA_CHIP_ID_BCM53018: 23 return true; 24 default: 25 return false; 26 } 27 } 28 29 /************************************************** 30 * BCMA bus ops 31 **************************************************/ 32 33 static u32 bcma_bgmac_read(struct bgmac *bgmac, u16 offset) 34 { 35 return bcma_read32(bgmac->bcma.core, offset); 36 } 37 38 static void bcma_bgmac_write(struct bgmac *bgmac, u16 offset, u32 value) 39 { 40 bcma_write32(bgmac->bcma.core, offset, value); 41 } 42 43 static u32 bcma_bgmac_idm_read(struct bgmac *bgmac, u16 offset) 44 { 45 return bcma_aread32(bgmac->bcma.core, offset); 46 } 47 48 static void bcma_bgmac_idm_write(struct bgmac *bgmac, u16 offset, u32 value) 49 { 50 return bcma_awrite32(bgmac->bcma.core, offset, value); 51 } 52 53 static bool bcma_bgmac_clk_enabled(struct bgmac *bgmac) 54 { 55 return bcma_core_is_enabled(bgmac->bcma.core); 56 } 57 58 static void bcma_bgmac_clk_enable(struct bgmac *bgmac, u32 flags) 59 { 60 bcma_core_enable(bgmac->bcma.core, flags); 61 } 62 63 static void bcma_bgmac_cco_ctl_maskset(struct bgmac *bgmac, u32 offset, 64 u32 mask, u32 set) 65 { 66 struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc; 67 68 bcma_chipco_chipctl_maskset(cc, offset, mask, set); 69 } 70 71 static u32 bcma_bgmac_get_bus_clock(struct bgmac *bgmac) 72 { 73 struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc; 74 75 return bcma_pmu_get_bus_clock(cc); 76 } 77 78 static void bcma_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset, u32 mask, 79 u32 set) 80 { 81 bcma_maskset32(bgmac->bcma.cmn, offset, mask, set); 82 } 83 84 static int bcma_phy_connect(struct bgmac *bgmac) 85 { 86 struct phy_device *phy_dev; 87 char bus_id[MII_BUS_ID_SIZE + 3]; 88 89 /* Connect to the PHY */ 90 snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id, 91 bgmac->phyaddr); 92 phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link, 93 PHY_INTERFACE_MODE_MII); 94 if (IS_ERR(phy_dev)) { 95 dev_err(bgmac->dev, "PHY connection failed\n"); 96 return PTR_ERR(phy_dev); 97 } 98 99 return 0; 100 } 101 102 static const struct bcma_device_id bgmac_bcma_tbl[] = { 103 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT, 104 BCMA_ANY_REV, BCMA_ANY_CLASS), 105 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_MAC_GBIT, BCMA_ANY_REV, 106 BCMA_ANY_CLASS), 107 {}, 108 }; 109 MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl); 110 111 /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */ 112 static int bgmac_probe(struct bcma_device *core) 113 { 114 struct bcma_chipinfo *ci = &core->bus->chipinfo; 115 struct ssb_sprom *sprom = &core->bus->sprom; 116 struct mii_bus *mii_bus; 117 struct bgmac *bgmac; 118 const u8 *mac; 119 int err; 120 121 bgmac = bgmac_alloc(&core->dev); 122 if (!bgmac) 123 return -ENOMEM; 124 125 bgmac->bcma.core = core; 126 bgmac->dma_dev = core->dma_dev; 127 bgmac->irq = core->irq; 128 129 bcma_set_drvdata(core, bgmac); 130 131 err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr); 132 133 /* If no MAC address assigned via device tree, check SPROM */ 134 if (err) { 135 switch (core->core_unit) { 136 case 0: 137 mac = sprom->et0mac; 138 break; 139 case 1: 140 mac = sprom->et1mac; 141 break; 142 case 2: 143 mac = sprom->et2mac; 144 break; 145 default: 146 dev_err(bgmac->dev, "Unsupported core_unit %d\n", 147 core->core_unit); 148 err = -ENOTSUPP; 149 goto err; 150 } 151 ether_addr_copy(bgmac->net_dev->dev_addr, mac); 152 } 153 154 /* On BCM4706 we need common core to access PHY */ 155 if (core->id.id == BCMA_CORE_4706_MAC_GBIT && 156 !core->bus->drv_gmac_cmn.core) { 157 dev_err(bgmac->dev, "GMAC CMN core not found (required for BCM4706)\n"); 158 err = -ENODEV; 159 goto err; 160 } 161 bgmac->bcma.cmn = core->bus->drv_gmac_cmn.core; 162 163 switch (core->core_unit) { 164 case 0: 165 bgmac->phyaddr = sprom->et0phyaddr; 166 break; 167 case 1: 168 bgmac->phyaddr = sprom->et1phyaddr; 169 break; 170 case 2: 171 bgmac->phyaddr = sprom->et2phyaddr; 172 break; 173 } 174 bgmac->phyaddr &= BGMAC_PHY_MASK; 175 if (bgmac->phyaddr == BGMAC_PHY_MASK) { 176 dev_err(bgmac->dev, "No PHY found\n"); 177 err = -ENODEV; 178 goto err; 179 } 180 dev_info(bgmac->dev, "Found PHY addr: %d%s\n", bgmac->phyaddr, 181 bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : ""); 182 183 if (!bgmac_is_bcm4707_family(core) && 184 !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) { 185 struct phy_device *phydev; 186 187 mii_bus = bcma_mdio_mii_register(bgmac); 188 if (IS_ERR(mii_bus)) { 189 err = PTR_ERR(mii_bus); 190 goto err; 191 } 192 bgmac->mii_bus = mii_bus; 193 194 phydev = mdiobus_get_phy(bgmac->mii_bus, bgmac->phyaddr); 195 if (ci->id == BCMA_CHIP_ID_BCM53573 && phydev && 196 (phydev->drv->phy_id & phydev->drv->phy_id_mask) == PHY_ID_BCM54210E) 197 phydev->dev_flags |= PHY_BRCM_EN_MASTER_MODE; 198 } 199 200 if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) { 201 dev_err(bgmac->dev, "PCI setup not implemented\n"); 202 err = -ENOTSUPP; 203 goto err1; 204 } 205 206 bgmac->has_robosw = !!(sprom->boardflags_lo & BGMAC_BFL_ENETROBO); 207 if (bgmac->has_robosw) 208 dev_warn(bgmac->dev, "Support for Roboswitch not implemented\n"); 209 210 if (sprom->boardflags_lo & BGMAC_BFL_ENETADM) 211 dev_warn(bgmac->dev, "Support for ADMtek ethernet switch not implemented\n"); 212 213 /* Feature Flags */ 214 switch (ci->id) { 215 /* BCM 471X/535X family */ 216 case BCMA_CHIP_ID_BCM4716: 217 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 218 fallthrough; 219 case BCMA_CHIP_ID_BCM47162: 220 bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL2; 221 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 222 break; 223 case BCMA_CHIP_ID_BCM5357: 224 case BCMA_CHIP_ID_BCM53572: 225 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 226 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 227 bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1; 228 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY; 229 if (ci->pkg == BCMA_PKG_ID_BCM47188 || 230 ci->pkg == BCMA_PKG_ID_BCM47186) { 231 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII; 232 bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; 233 } 234 if (ci->pkg == BCMA_PKG_ID_BCM5358) 235 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII; 236 break; 237 case BCMA_CHIP_ID_BCM53573: 238 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 239 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 240 if (ci->pkg == BCMA_PKG_ID_BCM47189) 241 bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; 242 if (core->core_unit == 0) { 243 bgmac->feature_flags |= BGMAC_FEAT_CC4_IF_SW_TYPE; 244 if (ci->pkg == BCMA_PKG_ID_BCM47189) 245 bgmac->feature_flags |= 246 BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII; 247 } else if (core->core_unit == 1) { 248 bgmac->feature_flags |= BGMAC_FEAT_IRQ_ID_OOB_6; 249 bgmac->feature_flags |= BGMAC_FEAT_CC7_IF_TYPE_RGMII; 250 } 251 break; 252 case BCMA_CHIP_ID_BCM4749: 253 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 254 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 255 bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1; 256 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY; 257 if (ci->pkg == 10) { 258 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII; 259 bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; 260 } 261 break; 262 /* bcm4707_family */ 263 case BCMA_CHIP_ID_BCM4707: 264 case BCMA_CHIP_ID_BCM47094: 265 case BCMA_CHIP_ID_BCM53018: 266 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 267 bgmac->feature_flags |= BGMAC_FEAT_NO_RESET; 268 bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500; 269 break; 270 default: 271 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 272 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 273 } 274 275 if (!bgmac_is_bcm4707_family(core) && core->id.rev > 2) 276 bgmac->feature_flags |= BGMAC_FEAT_MISC_PLL_REQ; 277 278 if (core->id.id == BCMA_CORE_4706_MAC_GBIT) { 279 bgmac->feature_flags |= BGMAC_FEAT_CMN_PHY_CTL; 280 bgmac->feature_flags |= BGMAC_FEAT_NO_CLR_MIB; 281 } 282 283 if (core->id.rev >= 4) { 284 bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4; 285 bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP; 286 bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP; 287 } 288 289 bgmac->read = bcma_bgmac_read; 290 bgmac->write = bcma_bgmac_write; 291 bgmac->idm_read = bcma_bgmac_idm_read; 292 bgmac->idm_write = bcma_bgmac_idm_write; 293 bgmac->clk_enabled = bcma_bgmac_clk_enabled; 294 bgmac->clk_enable = bcma_bgmac_clk_enable; 295 bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset; 296 bgmac->get_bus_clock = bcma_bgmac_get_bus_clock; 297 bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32; 298 if (bgmac->mii_bus) 299 bgmac->phy_connect = bcma_phy_connect; 300 else 301 bgmac->phy_connect = bgmac_phy_connect_direct; 302 303 err = bgmac_enet_probe(bgmac); 304 if (err) 305 goto err1; 306 307 return 0; 308 309 err1: 310 bcma_mdio_mii_unregister(bgmac->mii_bus); 311 err: 312 bcma_set_drvdata(core, NULL); 313 314 return err; 315 } 316 317 static void bgmac_remove(struct bcma_device *core) 318 { 319 struct bgmac *bgmac = bcma_get_drvdata(core); 320 321 bcma_mdio_mii_unregister(bgmac->mii_bus); 322 bgmac_enet_remove(bgmac); 323 bcma_set_drvdata(core, NULL); 324 kfree(bgmac); 325 } 326 327 static struct bcma_driver bgmac_bcma_driver = { 328 .name = KBUILD_MODNAME, 329 .id_table = bgmac_bcma_tbl, 330 .probe = bgmac_probe, 331 .remove = bgmac_remove, 332 }; 333 334 static int __init bgmac_init(void) 335 { 336 int err; 337 338 err = bcma_driver_register(&bgmac_bcma_driver); 339 if (err) 340 return err; 341 pr_info("Broadcom 47xx GBit MAC driver loaded\n"); 342 343 return 0; 344 } 345 346 static void __exit bgmac_exit(void) 347 { 348 bcma_driver_unregister(&bgmac_bcma_driver); 349 } 350 351 module_init(bgmac_init) 352 module_exit(bgmac_exit) 353 354 MODULE_AUTHOR("Rafał Miłecki"); 355 MODULE_LICENSE("GPL"); 356