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