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 phy_device *phydev; 302 unsigned int phy_flags; 303 int ret; 304 305 if (priv->phydev) { 306 pr_info("PHY already attached\n"); 307 return 0; 308 } 309 310 if (priv->phy_dn) 311 phydev = of_phy_connect(dev, priv->phy_dn, 312 bcmgenet_mii_setup, 0, 313 priv->phy_interface); 314 else 315 phydev = of_phy_connect_fixed_link(dev, 316 bcmgenet_mii_setup, 317 priv->phy_interface); 318 319 if (!phydev) { 320 pr_err("could not attach to PHY\n"); 321 return -ENODEV; 322 } 323 324 priv->old_link = -1; 325 priv->old_duplex = -1; 326 priv->old_pause = -1; 327 priv->phydev = phydev; 328 329 /* Configure port multiplexer based on what the probed PHY device since 330 * reading the 'max-speed' property determines the maximum supported 331 * PHY speed which is needed for bcmgenet_mii_config() to configure 332 * things appropriately. 333 */ 334 ret = bcmgenet_mii_config(dev); 335 if (ret) { 336 phy_disconnect(priv->phydev); 337 return ret; 338 } 339 340 phy_flags = PHY_BRCM_100MBPS_WAR; 341 342 /* workarounds are only needed for 100Mpbs PHYs, and 343 * never on GENET V1 hardware 344 */ 345 if ((phydev->supported & PHY_GBIT_FEATURES) || GENET_IS_V1(priv)) 346 phy_flags = 0; 347 348 phydev->dev_flags |= phy_flags; 349 phydev->advertising = phydev->supported; 350 351 /* The internal PHY has its link interrupts routed to the 352 * Ethernet MAC ISRs 353 */ 354 if (phy_is_internal(priv->phydev)) 355 priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT; 356 else 357 priv->mii_bus->irq[phydev->addr] = PHY_POLL; 358 359 pr_info("attached PHY at address %d [%s]\n", 360 phydev->addr, phydev->drv->name); 361 362 return 0; 363 } 364 365 static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv) 366 { 367 struct mii_bus *bus; 368 369 if (priv->mii_bus) 370 return 0; 371 372 priv->mii_bus = mdiobus_alloc(); 373 if (!priv->mii_bus) { 374 pr_err("failed to allocate\n"); 375 return -ENOMEM; 376 } 377 378 bus = priv->mii_bus; 379 bus->priv = priv->dev; 380 bus->name = "bcmgenet MII bus"; 381 bus->parent = &priv->pdev->dev; 382 bus->read = bcmgenet_mii_read; 383 bus->write = bcmgenet_mii_write; 384 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", 385 priv->pdev->name, priv->pdev->id); 386 387 bus->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 388 if (!bus->irq) { 389 mdiobus_free(priv->mii_bus); 390 return -ENOMEM; 391 } 392 393 return 0; 394 } 395 396 static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv) 397 { 398 struct device_node *dn = priv->pdev->dev.of_node; 399 struct device *kdev = &priv->pdev->dev; 400 struct device_node *mdio_dn; 401 char *compat; 402 int ret; 403 404 compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version); 405 if (!compat) 406 return -ENOMEM; 407 408 mdio_dn = of_find_compatible_node(dn, NULL, compat); 409 kfree(compat); 410 if (!mdio_dn) { 411 dev_err(kdev, "unable to find MDIO bus node\n"); 412 return -ENODEV; 413 } 414 415 ret = of_mdiobus_register(priv->mii_bus, mdio_dn); 416 if (ret) { 417 dev_err(kdev, "failed to register MDIO bus\n"); 418 return ret; 419 } 420 421 /* Fetch the PHY phandle */ 422 priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0); 423 424 /* Get the link mode */ 425 priv->phy_interface = of_get_phy_mode(dn); 426 427 return 0; 428 } 429 430 int bcmgenet_mii_init(struct net_device *dev) 431 { 432 struct bcmgenet_priv *priv = netdev_priv(dev); 433 int ret; 434 435 ret = bcmgenet_mii_alloc(priv); 436 if (ret) 437 return ret; 438 439 ret = bcmgenet_mii_of_init(priv); 440 if (ret) 441 goto out_free; 442 443 ret = bcmgenet_mii_probe(dev); 444 if (ret) 445 goto out; 446 447 return 0; 448 449 out: 450 mdiobus_unregister(priv->mii_bus); 451 out_free: 452 kfree(priv->mii_bus->irq); 453 mdiobus_free(priv->mii_bus); 454 return ret; 455 } 456 457 void bcmgenet_mii_exit(struct net_device *dev) 458 { 459 struct bcmgenet_priv *priv = netdev_priv(dev); 460 461 mdiobus_unregister(priv->mii_bus); 462 kfree(priv->mii_bus->irq); 463 mdiobus_free(priv->mii_bus); 464 } 465