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