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 = kzalloc(sizeof(*bgmac), GFP_KERNEL); 121 if (!bgmac) 122 return -ENOMEM; 123 124 bgmac->bcma.core = core; 125 bgmac->dev = &core->dev; 126 bgmac->dma_dev = core->dma_dev; 127 bgmac->irq = core->irq; 128 129 bcma_set_drvdata(core, bgmac); 130 131 switch (core->core_unit) { 132 case 0: 133 mac = sprom->et0mac; 134 break; 135 case 1: 136 mac = sprom->et1mac; 137 break; 138 case 2: 139 mac = sprom->et2mac; 140 break; 141 default: 142 dev_err(bgmac->dev, "Unsupported core_unit %d\n", 143 core->core_unit); 144 err = -ENOTSUPP; 145 goto err; 146 } 147 148 ether_addr_copy(bgmac->mac_addr, mac); 149 150 /* On BCM4706 we need common core to access PHY */ 151 if (core->id.id == BCMA_CORE_4706_MAC_GBIT && 152 !core->bus->drv_gmac_cmn.core) { 153 dev_err(bgmac->dev, "GMAC CMN core not found (required for BCM4706)\n"); 154 err = -ENODEV; 155 goto err; 156 } 157 bgmac->bcma.cmn = core->bus->drv_gmac_cmn.core; 158 159 switch (core->core_unit) { 160 case 0: 161 bgmac->phyaddr = sprom->et0phyaddr; 162 break; 163 case 1: 164 bgmac->phyaddr = sprom->et1phyaddr; 165 break; 166 case 2: 167 bgmac->phyaddr = sprom->et2phyaddr; 168 break; 169 } 170 bgmac->phyaddr &= BGMAC_PHY_MASK; 171 if (bgmac->phyaddr == BGMAC_PHY_MASK) { 172 dev_err(bgmac->dev, "No PHY found\n"); 173 err = -ENODEV; 174 goto err; 175 } 176 dev_info(bgmac->dev, "Found PHY addr: %d%s\n", bgmac->phyaddr, 177 bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : ""); 178 179 if (!bgmac_is_bcm4707_family(core) && 180 !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) { 181 mii_bus = bcma_mdio_mii_register(core, bgmac->phyaddr); 182 if (IS_ERR(mii_bus)) { 183 err = PTR_ERR(mii_bus); 184 goto err; 185 } 186 187 bgmac->mii_bus = mii_bus; 188 } 189 190 if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) { 191 dev_err(bgmac->dev, "PCI setup not implemented\n"); 192 err = -ENOTSUPP; 193 goto err1; 194 } 195 196 bgmac->has_robosw = !!(core->bus->sprom.boardflags_lo & 197 BGMAC_BFL_ENETROBO); 198 if (bgmac->has_robosw) 199 dev_warn(bgmac->dev, "Support for Roboswitch not implemented\n"); 200 201 if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM) 202 dev_warn(bgmac->dev, "Support for ADMtek ethernet switch not implemented\n"); 203 204 /* Feature Flags */ 205 switch (core->bus->chipinfo.id) { 206 case BCMA_CHIP_ID_BCM5357: 207 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 208 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 209 bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1; 210 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY; 211 if (core->bus->chipinfo.pkg == BCMA_PKG_ID_BCM47186) { 212 bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; 213 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII; 214 } 215 if (core->bus->chipinfo.pkg == BCMA_PKG_ID_BCM5358) 216 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII; 217 break; 218 case BCMA_CHIP_ID_BCM53572: 219 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 220 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 221 bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1; 222 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY; 223 if (core->bus->chipinfo.pkg == BCMA_PKG_ID_BCM47188) { 224 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII; 225 bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; 226 } 227 break; 228 case BCMA_CHIP_ID_BCM4749: 229 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 230 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 231 bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1; 232 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY; 233 if (core->bus->chipinfo.pkg == 10) { 234 bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII; 235 bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; 236 } 237 break; 238 case BCMA_CHIP_ID_BCM4716: 239 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 240 /* fallthrough */ 241 case BCMA_CHIP_ID_BCM47162: 242 bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL2; 243 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 244 break; 245 /* bcm4707_family */ 246 case BCMA_CHIP_ID_BCM4707: 247 case BCMA_CHIP_ID_BCM47094: 248 case BCMA_CHIP_ID_BCM53018: 249 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 250 bgmac->feature_flags |= BGMAC_FEAT_NO_RESET; 251 bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500; 252 break; 253 case BCMA_CHIP_ID_BCM53573: 254 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 255 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 256 if (ci->pkg == BCMA_PKG_ID_BCM47189) 257 bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; 258 if (core->core_unit == 0) { 259 bgmac->feature_flags |= BGMAC_FEAT_CC4_IF_SW_TYPE; 260 if (ci->pkg == BCMA_PKG_ID_BCM47189) 261 bgmac->feature_flags |= 262 BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII; 263 } else if (core->core_unit == 1) { 264 bgmac->feature_flags |= BGMAC_FEAT_IRQ_ID_OOB_6; 265 bgmac->feature_flags |= BGMAC_FEAT_CC7_IF_TYPE_RGMII; 266 } 267 break; 268 default: 269 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; 270 bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; 271 } 272 273 if (!bgmac_is_bcm4707_family(core) && core->id.rev > 2) 274 bgmac->feature_flags |= BGMAC_FEAT_MISC_PLL_REQ; 275 276 if (core->id.id == BCMA_CORE_4706_MAC_GBIT) { 277 bgmac->feature_flags |= BGMAC_FEAT_CMN_PHY_CTL; 278 bgmac->feature_flags |= BGMAC_FEAT_NO_CLR_MIB; 279 } 280 281 if (core->id.rev >= 4) { 282 bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4; 283 bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP; 284 bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP; 285 } 286 287 bgmac->read = bcma_bgmac_read; 288 bgmac->write = bcma_bgmac_write; 289 bgmac->idm_read = bcma_bgmac_idm_read; 290 bgmac->idm_write = bcma_bgmac_idm_write; 291 bgmac->clk_enabled = bcma_bgmac_clk_enabled; 292 bgmac->clk_enable = bcma_bgmac_clk_enable; 293 bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset; 294 bgmac->get_bus_clock = bcma_bgmac_get_bus_clock; 295 bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32; 296 if (bgmac->mii_bus) 297 bgmac->phy_connect = bcma_phy_connect; 298 else 299 bgmac->phy_connect = bgmac_phy_connect_direct; 300 301 err = bgmac_enet_probe(bgmac); 302 if (err) 303 goto err1; 304 305 return 0; 306 307 err1: 308 bcma_mdio_mii_unregister(bgmac->mii_bus); 309 err: 310 kfree(bgmac); 311 bcma_set_drvdata(core, NULL); 312 313 return err; 314 } 315 316 static void bgmac_remove(struct bcma_device *core) 317 { 318 struct bgmac *bgmac = bcma_get_drvdata(core); 319 320 bcma_mdio_mii_unregister(bgmac->mii_bus); 321 bgmac_enet_remove(bgmac); 322 bcma_set_drvdata(core, NULL); 323 kfree(bgmac); 324 } 325 326 static struct bcma_driver bgmac_bcma_driver = { 327 .name = KBUILD_MODNAME, 328 .id_table = bgmac_bcma_tbl, 329 .probe = bgmac_probe, 330 .remove = bgmac_remove, 331 }; 332 333 static int __init bgmac_init(void) 334 { 335 int err; 336 337 err = bcma_driver_register(&bgmac_bcma_driver); 338 if (err) 339 return err; 340 pr_info("Broadcom 47xx GBit MAC driver loaded\n"); 341 342 return 0; 343 } 344 345 static void __exit bgmac_exit(void) 346 { 347 bcma_driver_unregister(&bgmac_bcma_driver); 348 } 349 350 module_init(bgmac_init) 351 module_exit(bgmac_exit) 352 353 MODULE_AUTHOR("Rafał Miłecki"); 354 MODULE_LICENSE("GPL"); 355