Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] PHY: Add support for configuring the PHY connection interface

Most PHYs connect to an ethernet controller over a GMII or MII
interface. However, a growing number are connected over
different interfaces, such as RGMII or SGMII.

The ethernet driver will tell the PHY what type of connection it
is by setting it manually, or passing it in through phy_connect
(or phy_attach).

Changes include:
* Updates to documentation
* Updates to PHY Lib consumers
* Changes to PHY Lib to add interface support
* Some minor changes to whitespace in phy.h
* gianfar driver now detects interface and passes appropriate
value to PHY Lib
Signed-off-by: Andrew Fleming <afleming@freescale.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>

authored by

Andy Fleming and committed by
Jeff Garzik
e8a2b6a4 cabdfb37

+93 -23
+9 -4
Documentation/networking/phy.txt
··· 1 1 2 2 ------- 3 3 PHY Abstraction Layer 4 - (Updated 2005-07-21) 4 + (Updated 2006-11-30) 5 5 6 6 Purpose 7 7 ··· 97 97 98 98 Next, you need to know the device name of the PHY connected to this device. 99 99 The name will look something like, "phy0:0", where the first number is the 100 - bus id, and the second is the PHY's address on that bus. 100 + bus id, and the second is the PHY's address on that bus. Typically, 101 + the bus is responsible for making its ID unique. 101 102 102 103 Now, to connect, just call this function: 103 104 104 - phydev = phy_connect(dev, phy_name, &adjust_link, flags); 105 + phydev = phy_connect(dev, phy_name, &adjust_link, flags, interface); 105 106 106 107 phydev is a pointer to the phy_device structure which represents the PHY. If 107 108 phy_connect is successful, it will return the pointer. dev, here, is the ··· 115 114 flags is a u32 which can optionally contain phy-specific flags. 116 115 This is useful if the system has put hardware restrictions on 117 116 the PHY/controller, of which the PHY needs to be aware. 117 + 118 + interface is a u32 which specifies the connection type used 119 + between the controller and the PHY. Examples are GMII, MII, 120 + RGMII, and SGMII. For a full list, see include/linux/phy.h 118 121 119 122 Now just make sure that phydev->supported and phydev->advertising have any 120 123 values pruned from them which don't make sense for your controller (a 10/100 ··· 196 191 start, or disables then frees them for stop. 197 192 198 193 struct phy_device * phy_attach(struct net_device *dev, const char *phy_id, 199 - u32 flags); 194 + u32 flags, phy_interface_t interface); 200 195 201 196 Attaches a network device to a particular PHY, binding the PHY to a generic 202 197 driver if none was found during bus initialization. Passes in
+2 -1
drivers/net/au1000_eth.c
··· 360 360 BUG_ON(!phydev); 361 361 BUG_ON(phydev->attached_dev); 362 362 363 - phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0); 363 + phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0, 364 + PHY_INTERFACE_MODE_MII); 364 365 365 366 if (IS_ERR(phydev)) { 366 367 printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+2 -1
drivers/net/fs_enet/fs_enet-main.c
··· 779 779 fep->oldspeed = 0; 780 780 fep->oldduplex = -1; 781 781 if(fep->fpi->bus_id) 782 - phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0); 782 + phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0, 783 + PHY_INTERFACE_MODE_MII); 783 784 else { 784 785 printk("No phy bus ID specified in BSP code\n"); 785 786 return -EINVAL;
+37 -2
drivers/net/gianfar.c
··· 9 9 * Author: Andy Fleming 10 10 * Maintainer: Kumar Gala 11 11 * 12 - * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. 12 + * Copyright (c) 2002-2006 Freescale Semiconductor, Inc. 13 13 * 14 14 * This program is free software; you can redistribute it and/or modify it 15 15 * under the terms of the GNU General Public License as published by the ··· 398 398 } 399 399 400 400 401 + /* Reads the controller's registers to determine what interface 402 + * connects it to the PHY. 403 + */ 404 + static phy_interface_t gfar_get_interface(struct net_device *dev) 405 + { 406 + struct gfar_private *priv = netdev_priv(dev); 407 + u32 ecntrl = gfar_read(&priv->regs->ecntrl); 408 + 409 + if (ecntrl & ECNTRL_SGMII_MODE) 410 + return PHY_INTERFACE_MODE_SGMII; 411 + 412 + if (ecntrl & ECNTRL_TBI_MODE) { 413 + if (ecntrl & ECNTRL_REDUCED_MODE) 414 + return PHY_INTERFACE_MODE_RTBI; 415 + else 416 + return PHY_INTERFACE_MODE_TBI; 417 + } 418 + 419 + if (ecntrl & ECNTRL_REDUCED_MODE) { 420 + if (ecntrl & ECNTRL_REDUCED_MII_MODE) 421 + return PHY_INTERFACE_MODE_RMII; 422 + else 423 + return PHY_INTERFACE_MODE_RGMII; 424 + } 425 + 426 + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT) 427 + return PHY_INTERFACE_MODE_GMII; 428 + 429 + return PHY_INTERFACE_MODE_MII; 430 + } 431 + 432 + 401 433 /* Initializes driver's PHY state, and attaches to the PHY. 402 434 * Returns 0 on success. 403 435 */ ··· 441 409 SUPPORTED_1000baseT_Full : 0; 442 410 struct phy_device *phydev; 443 411 char phy_id[BUS_ID_SIZE]; 412 + phy_interface_t interface; 444 413 445 414 priv->oldlink = 0; 446 415 priv->oldspeed = 0; ··· 449 416 450 417 snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id); 451 418 452 - phydev = phy_connect(dev, phy_id, &adjust_link, 0); 419 + interface = gfar_get_interface(dev); 420 + 421 + phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface); 453 422 454 423 if (IS_ERR(phydev)) { 455 424 printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+3
drivers/net/gianfar.h
··· 160 160 161 161 #define ECNTRL_INIT_SETTINGS 0x00001000 162 162 #define ECNTRL_TBI_MODE 0x00000020 163 + #define ECNTRL_REDUCED_MODE 0x00000010 163 164 #define ECNTRL_R100 0x00000008 165 + #define ECNTRL_REDUCED_MII_MODE 0x00000004 166 + #define ECNTRL_SGMII_MODE 0x00000002 164 167 165 168 #define MRBLR_INIT_SETTINGS DEFAULT_RX_BUFFER_SIZE 166 169
+20 -9
drivers/net/phy/phy_device.c
··· 59 59 dev->duplex = -1; 60 60 dev->pause = dev->asym_pause = 0; 61 61 dev->link = 1; 62 + dev->interface = PHY_INTERFACE_MODE_GMII; 62 63 63 64 dev->autoneg = AUTONEG_ENABLE; 64 65 ··· 138 137 * the desired functionality. 139 138 */ 140 139 struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, 141 - void (*handler)(struct net_device *), u32 flags) 140 + void (*handler)(struct net_device *), u32 flags, 141 + u32 interface) 142 142 { 143 143 struct phy_device *phydev; 144 144 145 - phydev = phy_attach(dev, phy_id, flags); 145 + phydev = phy_attach(dev, phy_id, flags, interface); 146 146 147 147 if (IS_ERR(phydev)) 148 148 return phydev; ··· 188 186 } 189 187 190 188 struct phy_device *phy_attach(struct net_device *dev, 191 - const char *phy_id, u32 flags) 189 + const char *phy_id, u32 flags, u32 interface) 192 190 { 193 191 struct bus_type *bus = &mdio_bus_type; 194 192 struct phy_device *phydev; ··· 232 230 phydev->attached_dev = dev; 233 231 234 232 phydev->dev_flags = flags; 233 + 234 + phydev->interface = interface; 235 + 236 + /* Do initial configuration here, now that 237 + * we have certain key parameters 238 + * (dev_flags and interface) */ 239 + if (phydev->drv->config_init) { 240 + int err; 241 + 242 + err = phydev->drv->config_init(phydev); 243 + 244 + if (err < 0) 245 + return ERR_PTR(err); 246 + } 235 247 236 248 return phydev; 237 249 } ··· 628 612 629 613 spin_unlock(&phydev->lock); 630 614 631 - if (err < 0) 632 - return err; 633 - 634 - if (phydev->drv->config_init) 635 - err = phydev->drv->config_init(phydev); 636 - 637 615 return err; 616 + 638 617 } 639 618 640 619 static int phy_remove(struct device *dev)
+20 -6
include/linux/phy.h
··· 47 47 #define PHY_HAS_INTERRUPT 0x00000001 48 48 #define PHY_HAS_MAGICANEG 0x00000002 49 49 50 + /* Interface Mode definitions */ 51 + typedef enum { 52 + PHY_INTERFACE_MODE_MII, 53 + PHY_INTERFACE_MODE_GMII, 54 + PHY_INTERFACE_MODE_SGMII, 55 + PHY_INTERFACE_MODE_TBI, 56 + PHY_INTERFACE_MODE_RMII, 57 + PHY_INTERFACE_MODE_RGMII, 58 + PHY_INTERFACE_MODE_RTBI 59 + } phy_interface_t; 60 + 50 61 #define MII_BUS_MAX 4 51 62 52 63 53 - #define PHY_INIT_TIMEOUT 100000 64 + #define PHY_INIT_TIMEOUT 100000 54 65 #define PHY_STATE_TIME 1 55 66 #define PHY_FORCE_TIMEOUT 10 56 67 #define PHY_AN_TIMEOUT 10 57 68 58 - #define PHY_MAX_ADDR 32 69 + #define PHY_MAX_ADDR 32 59 70 60 71 /* Used when trying to connect to a specific phy (mii bus id:phy device id) */ 61 72 #define PHY_ID_FMT "%x:%02x" ··· 98 87 int *irq; 99 88 }; 100 89 101 - #define PHY_INTERRUPT_DISABLED 0x0 102 - #define PHY_INTERRUPT_ENABLED 0x80000000 90 + #define PHY_INTERRUPT_DISABLED 0x0 91 + #define PHY_INTERRUPT_ENABLED 0x80000000 103 92 104 93 /* PHY state machine states: 105 94 * ··· 241 230 242 231 u32 dev_flags; 243 232 233 + phy_interface_t interface; 234 + 244 235 /* Bus address of the PHY (0-32) */ 245 236 int addr; 246 237 ··· 358 345 int phy_clear_interrupt(struct phy_device *phydev); 359 346 int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); 360 347 struct phy_device * phy_attach(struct net_device *dev, 361 - const char *phy_id, u32 flags); 348 + const char *phy_id, u32 flags, phy_interface_t interface); 362 349 struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, 363 - void (*handler)(struct net_device *), u32 flags); 350 + void (*handler)(struct net_device *), u32 flags, 351 + phy_interface_t interface); 364 352 void phy_disconnect(struct phy_device *phydev); 365 353 void phy_detach(struct phy_device *phydev); 366 354 void phy_start(struct phy_device *phydev);