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