1 /* 2 * Broadcom GENET MDIO routines 3 * 4 * Copyright (c) 2014 Broadcom Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 */ 19 20 21 #include <linux/types.h> 22 #include <linux/delay.h> 23 #include <linux/wait.h> 24 #include <linux/mii.h> 25 #include <linux/ethtool.h> 26 #include <linux/bitops.h> 27 #include <linux/netdevice.h> 28 #include <linux/platform_device.h> 29 #include <linux/phy.h> 30 #include <linux/phy_fixed.h> 31 #include <linux/brcmphy.h> 32 #include <linux/of.h> 33 #include <linux/of_net.h> 34 #include <linux/of_mdio.h> 35 36 #include "bcmgenet.h" 37 38 /* read a value from the MII */ 39 static int bcmgenet_mii_read(struct mii_bus *bus, int phy_id, int location) 40 { 41 int ret; 42 struct net_device *dev = bus->priv; 43 struct bcmgenet_priv *priv = netdev_priv(dev); 44 u32 reg; 45 46 bcmgenet_umac_writel(priv, (MDIO_RD | (phy_id << MDIO_PMD_SHIFT) | 47 (location << MDIO_REG_SHIFT)), UMAC_MDIO_CMD); 48 /* Start MDIO transaction*/ 49 reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD); 50 reg |= MDIO_START_BUSY; 51 bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD); 52 wait_event_timeout(priv->wq, 53 !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD) 54 & MDIO_START_BUSY), 55 HZ / 100); 56 ret = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD); 57 58 if (ret & MDIO_READ_FAIL) 59 return -EIO; 60 61 return ret & 0xffff; 62 } 63 64 /* write a value to the MII */ 65 static int bcmgenet_mii_write(struct mii_bus *bus, int phy_id, 66 int location, u16 val) 67 { 68 struct net_device *dev = bus->priv; 69 struct bcmgenet_priv *priv = netdev_priv(dev); 70 u32 reg; 71 72 bcmgenet_umac_writel(priv, (MDIO_WR | (phy_id << MDIO_PMD_SHIFT) | 73 (location << MDIO_REG_SHIFT) | (0xffff & val)), 74 UMAC_MDIO_CMD); 75 reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD); 76 reg |= MDIO_START_BUSY; 77 bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD); 78 wait_event_timeout(priv->wq, 79 !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD) & 80 MDIO_START_BUSY), 81 HZ / 100); 82 83 return 0; 84 } 85 86 /* setup netdev link state when PHY link status change and 87 * update UMAC and RGMII block when link up 88 */ 89 static void bcmgenet_mii_setup(struct net_device *dev) 90 { 91 struct bcmgenet_priv *priv = netdev_priv(dev); 92 struct phy_device *phydev = priv->phydev; 93 u32 reg, cmd_bits = 0; 94 unsigned int status_changed = 0; 95 96 if (priv->old_link != phydev->link) { 97 status_changed = 1; 98 priv->old_link = phydev->link; 99 } 100 101 if (phydev->link) { 102 /* program UMAC and RGMII block based on established link 103 * speed, pause, and duplex. 104 * the speed set in umac->cmd tell RGMII block which clock 105 * 25MHz(100Mbps)/125MHz(1Gbps) to use for transmit. 106 * receive clock is provided by PHY. 107 */ 108 reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); 109 reg &= ~OOB_DISABLE; 110 reg |= RGMII_LINK; 111 bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); 112 113 /* speed */ 114 if (phydev->speed == SPEED_1000) 115 cmd_bits = UMAC_SPEED_1000; 116 else if (phydev->speed == SPEED_100) 117 cmd_bits = UMAC_SPEED_100; 118 else 119 cmd_bits = UMAC_SPEED_10; 120 cmd_bits <<= CMD_SPEED_SHIFT; 121 122 if (priv->old_duplex != phydev->duplex) { 123 status_changed = 1; 124 priv->old_duplex = phydev->duplex; 125 } 126 127 /* duplex */ 128 if (phydev->duplex != DUPLEX_FULL) 129 cmd_bits |= CMD_HD_EN; 130 131 if (priv->old_pause != phydev->pause) { 132 status_changed = 1; 133 priv->old_pause = phydev->pause; 134 } 135 136 /* pause capability */ 137 if (!phydev->pause) 138 cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE; 139 140 reg = bcmgenet_umac_readl(priv, UMAC_CMD); 141 reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) | 142 CMD_HD_EN | 143 CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE); 144 reg |= cmd_bits; 145 bcmgenet_umac_writel(priv, reg, UMAC_CMD); 146 } 147 148 if (status_changed) 149 phy_print_status(phydev); 150 } 151 152 void bcmgenet_mii_reset(struct net_device *dev) 153 { 154 struct bcmgenet_priv *priv = netdev_priv(dev); 155 156 if (priv->phydev) { 157 phy_init_hw(priv->phydev); 158 phy_start_aneg(priv->phydev); 159 } 160 } 161 162 static void bcmgenet_ephy_power_up(struct net_device *dev) 163 { 164 struct bcmgenet_priv *priv = netdev_priv(dev); 165 u32 reg = 0; 166 167 /* EXT_GPHY_CTRL is only valid for GENETv4 and onward */ 168 if (!GENET_IS_V4(priv)) 169 return; 170 171 reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL); 172 reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN); 173 reg |= EXT_GPHY_RESET; 174 bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); 175 mdelay(2); 176 177 reg &= ~EXT_GPHY_RESET; 178 bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); 179 udelay(20); 180 } 181 182 static void bcmgenet_internal_phy_setup(struct net_device *dev) 183 { 184 struct bcmgenet_priv *priv = netdev_priv(dev); 185 u32 reg; 186 187 /* Power up EPHY */ 188 bcmgenet_ephy_power_up(dev); 189 /* enable APD */ 190 reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); 191 reg |= EXT_PWR_DN_EN_LD; 192 bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); 193 bcmgenet_mii_reset(dev); 194 } 195 196 static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) 197 { 198 u32 reg; 199 200 /* Speed settings are set in bcmgenet_mii_setup() */ 201 reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL); 202 reg |= LED_ACT_SOURCE_MAC; 203 bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL); 204 } 205 206 int bcmgenet_mii_config(struct net_device *dev) 207 { 208 struct bcmgenet_priv *priv = netdev_priv(dev); 209 struct phy_device *phydev = priv->phydev; 210 struct device *kdev = &priv->pdev->dev; 211 const char *phy_name = NULL; 212 u32 id_mode_dis = 0; 213 u32 port_ctrl; 214 u32 reg; 215 216 priv->ext_phy = !phy_is_internal(priv->phydev) && 217 (priv->phy_interface != PHY_INTERFACE_MODE_MOCA); 218 219 if (phy_is_internal(priv->phydev)) 220 priv->phy_interface = PHY_INTERFACE_MODE_NA; 221 222 switch (priv->phy_interface) { 223 case PHY_INTERFACE_MODE_NA: 224 case PHY_INTERFACE_MODE_MOCA: 225 /* Irrespective of the actually configured PHY speed (100 or 226 * 1000) GENETv4 only has an internal GPHY so we will just end 227 * up masking the Gigabit features from what we support, not 228 * switching to the EPHY 229 */ 230 if (GENET_IS_V4(priv)) 231 port_ctrl = PORT_MODE_INT_GPHY; 232 else 233 port_ctrl = PORT_MODE_INT_EPHY; 234 235 bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL); 236 237 if (phy_is_internal(priv->phydev)) { 238 phy_name = "internal PHY"; 239 bcmgenet_internal_phy_setup(dev); 240 } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { 241 phy_name = "MoCA"; 242 bcmgenet_moca_phy_setup(priv); 243 } 244 break; 245 246 case PHY_INTERFACE_MODE_MII: 247 phy_name = "external MII"; 248 phydev->supported &= PHY_BASIC_FEATURES; 249 bcmgenet_sys_writel(priv, 250 PORT_MODE_EXT_EPHY, SYS_PORT_CTRL); 251 break; 252 253 case PHY_INTERFACE_MODE_REVMII: 254 phy_name = "external RvMII"; 255 /* of_mdiobus_register took care of reading the 'max-speed' 256 * PHY property for us, effectively limiting the PHY supported 257 * capabilities, use that knowledge to also configure the 258 * Reverse MII interface correctly. 259 */ 260 if ((priv->phydev->supported & PHY_BASIC_FEATURES) == 261 PHY_BASIC_FEATURES) 262 port_ctrl = PORT_MODE_EXT_RVMII_25; 263 else 264 port_ctrl = PORT_MODE_EXT_RVMII_50; 265 bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL); 266 break; 267 268 case PHY_INTERFACE_MODE_RGMII: 269 /* RGMII_NO_ID: TXC transitions at the same time as TXD 270 * (requires PCB or receiver-side delay) 271 * RGMII: Add 2ns delay on TXC (90 degree shift) 272 * 273 * ID is implicitly disabled for 100Mbps (RG)MII operation. 274 */ 275 id_mode_dis = BIT(16); 276 /* fall through */ 277 case PHY_INTERFACE_MODE_RGMII_TXID: 278 if (id_mode_dis) 279 phy_name = "external RGMII (no delay)"; 280 else 281 phy_name = "external RGMII (TX delay)"; 282 reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); 283 reg |= RGMII_MODE_EN | id_mode_dis; 284 bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); 285 bcmgenet_sys_writel(priv, 286 PORT_MODE_EXT_GPHY, SYS_PORT_CTRL); 287 break; 288 default: 289 dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface); 290 return -EINVAL; 291 } 292 293 dev_info(kdev, "configuring instance for %s\n", phy_name); 294 295 return 0; 296 } 297 298 static int bcmgenet_mii_probe(struct net_device *dev) 299 { 300 struct bcmgenet_priv *priv = netdev_priv(dev); 301 struct device_node *dn = priv->pdev->dev.of_node; 302 struct phy_device *phydev; 303 unsigned int phy_flags; 304 int ret; 305 306 if (priv->phydev) { 307 pr_info("PHY already attached\n"); 308 return 0; 309 } 310 311 /* In the case of a fixed PHY, the DT node associated 312 * to the PHY is the Ethernet MAC DT node. 313 */ 314 if (of_phy_is_fixed_link(dn)) { 315 ret = of_phy_register_fixed_link(dn); 316 if (ret) 317 return ret; 318 319 priv->phy_dn = dn; 320 } 321 322 phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, 0, 323 priv->phy_interface); 324 if (!phydev) { 325 pr_err("could not attach to PHY\n"); 326 return -ENODEV; 327 } 328 329 priv->old_link = -1; 330 priv->old_duplex = -1; 331 priv->old_pause = -1; 332 priv->phydev = phydev; 333 334 /* Configure port multiplexer based on what the probed PHY device since 335 * reading the 'max-speed' property determines the maximum supported 336 * PHY speed which is needed for bcmgenet_mii_config() to configure 337 * things appropriately. 338 */ 339 ret = bcmgenet_mii_config(dev); 340 if (ret) { 341 phy_disconnect(priv->phydev); 342 return ret; 343 } 344 345 phy_flags = PHY_BRCM_100MBPS_WAR; 346 347 /* workarounds are only needed for 100Mpbs PHYs, and 348 * never on GENET V1 hardware 349 */ 350 if ((phydev->supported & PHY_GBIT_FEATURES) || GENET_IS_V1(priv)) 351 phy_flags = 0; 352 353 phydev->dev_flags |= phy_flags; 354 phydev->advertising = phydev->supported; 355 356 /* The internal PHY has its link interrupts routed to the 357 * Ethernet MAC ISRs 358 */ 359 if (phy_is_internal(priv->phydev)) 360 priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT; 361 else 362 priv->mii_bus->irq[phydev->addr] = PHY_POLL; 363 364 pr_info("attached PHY at address %d [%s]\n", 365 phydev->addr, phydev->drv->name); 366 367 return 0; 368 } 369 370 static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv) 371 { 372 struct mii_bus *bus; 373 374 if (priv->mii_bus) 375 return 0; 376 377 priv->mii_bus = mdiobus_alloc(); 378 if (!priv->mii_bus) { 379 pr_err("failed to allocate\n"); 380 return -ENOMEM; 381 } 382 383 bus = priv->mii_bus; 384 bus->priv = priv->dev; 385 bus->name = "bcmgenet MII bus"; 386 bus->parent = &priv->pdev->dev; 387 bus->read = bcmgenet_mii_read; 388 bus->write = bcmgenet_mii_write; 389 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", 390 priv->pdev->name, priv->pdev->id); 391 392 bus->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 393 if (!bus->irq) { 394 mdiobus_free(priv->mii_bus); 395 return -ENOMEM; 396 } 397 398 return 0; 399 } 400 401 static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv) 402 { 403 struct device_node *dn = priv->pdev->dev.of_node; 404 struct device *kdev = &priv->pdev->dev; 405 struct device_node *mdio_dn; 406 char *compat; 407 int ret; 408 409 compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version); 410 if (!compat) 411 return -ENOMEM; 412 413 mdio_dn = of_find_compatible_node(dn, NULL, compat); 414 kfree(compat); 415 if (!mdio_dn) { 416 dev_err(kdev, "unable to find MDIO bus node\n"); 417 return -ENODEV; 418 } 419 420 ret = of_mdiobus_register(priv->mii_bus, mdio_dn); 421 if (ret) { 422 dev_err(kdev, "failed to register MDIO bus\n"); 423 return ret; 424 } 425 426 /* Fetch the PHY phandle */ 427 priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0); 428 429 /* Get the link mode */ 430 priv->phy_interface = of_get_phy_mode(dn); 431 432 return 0; 433 } 434 435 int bcmgenet_mii_init(struct net_device *dev) 436 { 437 struct bcmgenet_priv *priv = netdev_priv(dev); 438 int ret; 439 440 ret = bcmgenet_mii_alloc(priv); 441 if (ret) 442 return ret; 443 444 ret = bcmgenet_mii_of_init(priv); 445 if (ret) 446 goto out_free; 447 448 ret = bcmgenet_mii_probe(dev); 449 if (ret) 450 goto out; 451 452 return 0; 453 454 out: 455 mdiobus_unregister(priv->mii_bus); 456 out_free: 457 kfree(priv->mii_bus->irq); 458 mdiobus_free(priv->mii_bus); 459 return ret; 460 } 461 462 void bcmgenet_mii_exit(struct net_device *dev) 463 { 464 struct bcmgenet_priv *priv = netdev_priv(dev); 465 466 mdiobus_unregister(priv->mii_bus); 467 kfree(priv->mii_bus->irq); 468 mdiobus_free(priv->mii_bus); 469 } 470