| ===================== | 
 | PHY Abstraction Layer | 
 | ===================== | 
 |  | 
 | Purpose | 
 | ======= | 
 |  | 
 | Most network devices consist of set of registers which provide an interface | 
 | to a MAC layer, which communicates with the physical connection through a | 
 | PHY.  The PHY concerns itself with negotiating link parameters with the link | 
 | partner on the other side of the network connection (typically, an ethernet | 
 | cable), and provides a register interface to allow drivers to determine what | 
 | settings were chosen, and to configure what settings are allowed. | 
 |  | 
 | While these devices are distinct from the network devices, and conform to a | 
 | standard layout for the registers, it has been common practice to integrate | 
 | the PHY management code with the network driver.  This has resulted in large | 
 | amounts of redundant code.  Also, on embedded systems with multiple (and | 
 | sometimes quite different) ethernet controllers connected to the same | 
 | management bus, it is difficult to ensure safe use of the bus. | 
 |  | 
 | Since the PHYs are devices, and the management busses through which they are | 
 | accessed are, in fact, busses, the PHY Abstraction Layer treats them as such. | 
 | In doing so, it has these goals: | 
 |  | 
 | #. Increase code-reuse | 
 | #. Increase overall code-maintainability | 
 | #. Speed development time for new network drivers, and for new systems | 
 |  | 
 | Basically, this layer is meant to provide an interface to PHY devices which | 
 | allows network driver writers to write as little code as possible, while | 
 | still providing a full feature set. | 
 |  | 
 | The MDIO bus | 
 | ============ | 
 |  | 
 | Most network devices are connected to a PHY by means of a management bus. | 
 | Different devices use different busses (though some share common interfaces). | 
 | In order to take advantage of the PAL, each bus interface needs to be | 
 | registered as a distinct device. | 
 |  | 
 | #. read and write functions must be implemented. Their prototypes are:: | 
 |  | 
 | 	int write(struct mii_bus *bus, int mii_id, int regnum, u16 value); | 
 | 	int read(struct mii_bus *bus, int mii_id, int regnum); | 
 |  | 
 |    mii_id is the address on the bus for the PHY, and regnum is the register | 
 |    number.  These functions are guaranteed not to be called from interrupt | 
 |    time, so it is safe for them to block, waiting for an interrupt to signal | 
 |    the operation is complete | 
 |  | 
 | #. A reset function is optional. This is used to return the bus to an | 
 |    initialized state. | 
 |  | 
 | #. A probe function is needed.  This function should set up anything the bus | 
 |    driver needs, setup the mii_bus structure, and register with the PAL using | 
 |    mdiobus_register.  Similarly, there's a remove function to undo all of | 
 |    that (use mdiobus_unregister). | 
 |  | 
 | #. Like any driver, the device_driver structure must be configured, and init | 
 |    exit functions are used to register the driver. | 
 |  | 
 | #. The bus must also be declared somewhere as a device, and registered. | 
 |  | 
 | As an example for how one driver implemented an mdio bus driver, see | 
 | drivers/net/ethernet/freescale/fsl_pq_mdio.c and an associated DTS file | 
 | for one of the users. (e.g. "git grep fsl,.*-mdio arch/powerpc/boot/dts/") | 
 |  | 
 | (RG)MII/electrical interface considerations | 
 | =========================================== | 
 |  | 
 | The Reduced Gigabit Medium Independent Interface (RGMII) is a 12-pin | 
 | electrical signal interface using a synchronous 125Mhz clock signal and several | 
 | data lines. Due to this design decision, a 1.5ns to 2ns delay must be added | 
 | between the clock line (RXC or TXC) and the data lines to let the PHY (clock | 
 | sink) have a large enough setup and hold time to sample the data lines correctly. The | 
 | PHY library offers different types of PHY_INTERFACE_MODE_RGMII* values to let | 
 | the PHY driver and optionally the MAC driver, implement the required delay. The | 
 | values of phy_interface_t must be understood from the perspective of the PHY | 
 | device itself, leading to the following: | 
 |  | 
 | * PHY_INTERFACE_MODE_RGMII: the PHY is not responsible for inserting any | 
 |   internal delay by itself, it assumes that either the Ethernet MAC (if capable | 
 |   or the PCB traces) insert the correct 1.5-2ns delay | 
 |  | 
 | * PHY_INTERFACE_MODE_RGMII_TXID: the PHY should insert an internal delay | 
 |   for the transmit data lines (TXD[3:0]) processed by the PHY device | 
 |  | 
 | * PHY_INTERFACE_MODE_RGMII_RXID: the PHY should insert an internal delay | 
 |   for the receive data lines (RXD[3:0]) processed by the PHY device | 
 |  | 
 | * PHY_INTERFACE_MODE_RGMII_ID: the PHY should insert internal delays for | 
 |   both transmit AND receive data lines from/to the PHY device | 
 |  | 
 | Whenever possible, use the PHY side RGMII delay for these reasons: | 
 |  | 
 | * PHY devices may offer sub-nanosecond granularity in how they allow a | 
 |   receiver/transmitter side delay (e.g: 0.5, 1.0, 1.5ns) to be specified. Such | 
 |   precision may be required to account for differences in PCB trace lengths | 
 |  | 
 | * PHY devices are typically qualified for a large range of applications | 
 |   (industrial, medical, automotive...), and they provide a constant and | 
 |   reliable delay across temperature/pressure/voltage ranges | 
 |  | 
 | * PHY device drivers in PHYLIB being reusable by nature, being able to | 
 |   configure correctly a specified delay enables more designs with similar delay | 
 |   requirements to be operate correctly | 
 |  | 
 | For cases where the PHY is not capable of providing this delay, but the | 
 | Ethernet MAC driver is capable of doing so, the correct phy_interface_t value | 
 | should be PHY_INTERFACE_MODE_RGMII, and the Ethernet MAC driver should be | 
 | configured correctly in order to provide the required transmit and/or receive | 
 | side delay from the perspective of the PHY device. Conversely, if the Ethernet | 
 | MAC driver looks at the phy_interface_t value, for any other mode but | 
 | PHY_INTERFACE_MODE_RGMII, it should make sure that the MAC-level delays are | 
 | disabled. | 
 |  | 
 | In case neither the Ethernet MAC, nor the PHY are capable of providing the | 
 | required delays, as defined per the RGMII standard, several options may be | 
 | available: | 
 |  | 
 | * Some SoCs may offer a pin pad/mux/controller capable of configuring a given | 
 |   set of pins'strength, delays, and voltage; and it may be a suitable | 
 |   option to insert the expected 2ns RGMII delay. | 
 |  | 
 | * Modifying the PCB design to include a fixed delay (e.g: using a specifically | 
 |   designed serpentine), which may not require software configuration at all. | 
 |  | 
 | Common problems with RGMII delay mismatch | 
 | ----------------------------------------- | 
 |  | 
 | When there is a RGMII delay mismatch between the Ethernet MAC and the PHY, this | 
 | will most likely result in the clock and data line signals to be unstable when | 
 | the PHY or MAC take a snapshot of these signals to translate them into logical | 
 | 1 or 0 states and reconstruct the data being transmitted/received. Typical | 
 | symptoms include: | 
 |  | 
 | * Transmission/reception partially works, and there is frequent or occasional | 
 |   packet loss observed | 
 |  | 
 | * Ethernet MAC may report some or all packets ingressing with a FCS/CRC error, | 
 |   or just discard them all | 
 |  | 
 | * Switching to lower speeds such as 10/100Mbits/sec makes the problem go away | 
 |   (since there is enough setup/hold time in that case) | 
 |  | 
 | Connecting to a PHY | 
 | =================== | 
 |  | 
 | Sometime during startup, the network driver needs to establish a connection | 
 | between the PHY device, and the network device.  At this time, the PHY's bus | 
 | and drivers need to all have been loaded, so it is ready for the connection. | 
 | At this point, there are several ways to connect to the PHY: | 
 |  | 
 | #. The PAL handles everything, and only calls the network driver when | 
 |    the link state changes, so it can react. | 
 |  | 
 | #. The PAL handles everything except interrupts (usually because the | 
 |    controller has the interrupt registers). | 
 |  | 
 | #. The PAL handles everything, but checks in with the driver every second, | 
 |    allowing the network driver to react first to any changes before the PAL | 
 |    does. | 
 |  | 
 | #. The PAL serves only as a library of functions, with the network device | 
 |    manually calling functions to update status, and configure the PHY | 
 |  | 
 |  | 
 | Letting the PHY Abstraction Layer do Everything | 
 | =============================================== | 
 |  | 
 | If you choose option 1 (The hope is that every driver can, but to still be | 
 | useful to drivers that can't), connecting to the PHY is simple: | 
 |  | 
 | First, you need a function to react to changes in the link state.  This | 
 | function follows this protocol:: | 
 |  | 
 | 	static void adjust_link(struct net_device *dev); | 
 |  | 
 | Next, you need to know the device name of the PHY connected to this device. | 
 | The name will look something like, "0:00", where the first number is the | 
 | bus id, and the second is the PHY's address on that bus.  Typically, | 
 | the bus is responsible for making its ID unique. | 
 |  | 
 | Now, to connect, just call this function:: | 
 |  | 
 | 	phydev = phy_connect(dev, phy_name, &adjust_link, interface); | 
 |  | 
 | *phydev* is a pointer to the phy_device structure which represents the PHY. | 
 | If phy_connect is successful, it will return the pointer.  dev, here, is the | 
 | pointer to your net_device.  Once done, this function will have started the | 
 | PHY's software state machine, and registered for the PHY's interrupt, if it | 
 | has one.  The phydev structure will be populated with information about the | 
 | current state, though the PHY will not yet be truly operational at this | 
 | point. | 
 |  | 
 | PHY-specific flags should be set in phydev->dev_flags prior to the call | 
 | to phy_connect() such that the underlying PHY driver can check for flags | 
 | and perform specific operations based on them. | 
 | This is useful if the system has put hardware restrictions on | 
 | the PHY/controller, of which the PHY needs to be aware. | 
 |  | 
 | *interface* is a u32 which specifies the connection type used | 
 | between the controller and the PHY.  Examples are GMII, MII, | 
 | RGMII, and SGMII.  See "PHY interface mode" below.  For a full | 
 | list, see include/linux/phy.h | 
 |  | 
 | Now just make sure that phydev->supported and phydev->advertising have any | 
 | values pruned from them which don't make sense for your controller (a 10/100 | 
 | controller may be connected to a gigabit capable PHY, so you would need to | 
 | mask off SUPPORTED_1000baseT*).  See include/linux/ethtool.h for definitions | 
 | for these bitfields. Note that you should not SET any bits, except the | 
 | SUPPORTED_Pause and SUPPORTED_AsymPause bits (see below), or the PHY may get | 
 | put into an unsupported state. | 
 |  | 
 | Lastly, once the controller is ready to handle network traffic, you call | 
 | phy_start(phydev).  This tells the PAL that you are ready, and configures the | 
 | PHY to connect to the network. If the MAC interrupt of your network driver | 
 | also handles PHY status changes, just set phydev->irq to PHY_IGNORE_INTERRUPT | 
 | before you call phy_start and use phy_mac_interrupt() from the network | 
 | driver. If you don't want to use interrupts, set phydev->irq to PHY_POLL. | 
 | phy_start() enables the PHY interrupts (if applicable) and starts the | 
 | phylib state machine. | 
 |  | 
 | When you want to disconnect from the network (even if just briefly), you call | 
 | phy_stop(phydev). This function also stops the phylib state machine and | 
 | disables PHY interrupts. | 
 |  | 
 | PHY interface modes | 
 | =================== | 
 |  | 
 | The PHY interface mode supplied in the phy_connect() family of functions | 
 | defines the initial operating mode of the PHY interface.  This is not | 
 | guaranteed to remain constant; there are PHYs which dynamically change | 
 | their interface mode without software interaction depending on the | 
 | negotiation results. | 
 |  | 
 | Some of the interface modes are described below: | 
 |  | 
 | ``PHY_INTERFACE_MODE_1000BASEX`` | 
 |     This defines the 1000BASE-X single-lane serdes link as defined by the | 
 |     802.3 standard section 36.  The link operates at a fixed bit rate of | 
 |     1.25Gbaud using a 10B/8B encoding scheme, resulting in an underlying | 
 |     data rate of 1Gbps.  Embedded in the data stream is a 16-bit control | 
 |     word which is used to negotiate the duplex and pause modes with the | 
 |     remote end.  This does not include "up-clocked" variants such as 2.5Gbps | 
 |     speeds (see below.) | 
 |  | 
 | ``PHY_INTERFACE_MODE_2500BASEX`` | 
 |     This defines a variant of 1000BASE-X which is clocked 2.5 times faster, | 
 |     than the 802.3 standard giving a fixed bit rate of 3.125Gbaud. | 
 |  | 
 | ``PHY_INTERFACE_MODE_SGMII`` | 
 |     This is used for Cisco SGMII, which is a modification of 1000BASE-X | 
 |     as defined by the 802.3 standard.  The SGMII link consists of a single | 
 |     serdes lane running at a fixed bit rate of 1.25Gbaud with 10B/8B | 
 |     encoding.  The underlying data rate is 1Gbps, with the slower speeds of | 
 |     100Mbps and 10Mbps being achieved through replication of each data symbol. | 
 |     The 802.3 control word is re-purposed to send the negotiated speed and | 
 |     duplex information from to the MAC, and for the MAC to acknowledge | 
 |     receipt.  This does not include "up-clocked" variants such as 2.5Gbps | 
 |     speeds. | 
 |  | 
 |     Note: mismatched SGMII vs 1000BASE-X configuration on a link can | 
 |     successfully pass data in some circumstances, but the 16-bit control | 
 |     word will not be correctly interpreted, which may cause mismatches in | 
 |     duplex, pause or other settings.  This is dependent on the MAC and/or | 
 |     PHY behaviour. | 
 |  | 
 | ``PHY_INTERFACE_MODE_10GBASER`` | 
 |     This is the IEEE 802.3 Clause 49 defined 10GBASE-R protocol used with | 
 |     various different mediums. Please refer to the IEEE standard for a | 
 |     definition of this. | 
 |  | 
 |     Note: 10GBASE-R is just one protocol that can be used with XFI and SFI. | 
 |     XFI and SFI permit multiple protocols over a single SERDES lane, and | 
 |     also defines the electrical characteristics of the signals with a host | 
 |     compliance board plugged into the host XFP/SFP connector. Therefore, | 
 |     XFI and SFI are not PHY interface types in their own right. | 
 |  | 
 | ``PHY_INTERFACE_MODE_10GKR`` | 
 |     This is the IEEE 802.3 Clause 49 defined 10GBASE-R with Clause 73 | 
 |     autonegotiation. Please refer to the IEEE standard for further | 
 |     information. | 
 |  | 
 |     Note: due to legacy usage, some 10GBASE-R usage incorrectly makes | 
 |     use of this definition. | 
 |  | 
 | Pause frames / flow control | 
 | =========================== | 
 |  | 
 | The PHY does not participate directly in flow control/pause frames except by | 
 | making sure that the SUPPORTED_Pause and SUPPORTED_AsymPause bits are set in | 
 | MII_ADVERTISE to indicate towards the link partner that the Ethernet MAC | 
 | controller supports such a thing. Since flow control/pause frames generation | 
 | involves the Ethernet MAC driver, it is recommended that this driver takes care | 
 | of properly indicating advertisement and support for such features by setting | 
 | the SUPPORTED_Pause and SUPPORTED_AsymPause bits accordingly. This can be done | 
 | either before or after phy_connect() and/or as a result of implementing the | 
 | ethtool::set_pauseparam feature. | 
 |  | 
 |  | 
 | Keeping Close Tabs on the PAL | 
 | ============================= | 
 |  | 
 | It is possible that the PAL's built-in state machine needs a little help to | 
 | keep your network device and the PHY properly in sync.  If so, you can | 
 | register a helper function when connecting to the PHY, which will be called | 
 | every second before the state machine reacts to any changes.  To do this, you | 
 | need to manually call phy_attach() and phy_prepare_link(), and then call | 
 | phy_start_machine() with the second argument set to point to your special | 
 | handler. | 
 |  | 
 | Currently there are no examples of how to use this functionality, and testing | 
 | on it has been limited because the author does not have any drivers which use | 
 | it (they all use option 1).  So Caveat Emptor. | 
 |  | 
 | Doing it all yourself | 
 | ===================== | 
 |  | 
 | There's a remote chance that the PAL's built-in state machine cannot track | 
 | the complex interactions between the PHY and your network device.  If this is | 
 | so, you can simply call phy_attach(), and not call phy_start_machine or | 
 | phy_prepare_link().  This will mean that phydev->state is entirely yours to | 
 | handle (phy_start and phy_stop toggle between some of the states, so you | 
 | might need to avoid them). | 
 |  | 
 | An effort has been made to make sure that useful functionality can be | 
 | accessed without the state-machine running, and most of these functions are | 
 | descended from functions which did not interact with a complex state-machine. | 
 | However, again, no effort has been made so far to test running without the | 
 | state machine, so tryer beware. | 
 |  | 
 | Here is a brief rundown of the functions:: | 
 |  | 
 |  int phy_read(struct phy_device *phydev, u16 regnum); | 
 |  int phy_write(struct phy_device *phydev, u16 regnum, u16 val); | 
 |  | 
 | Simple read/write primitives.  They invoke the bus's read/write function | 
 | pointers. | 
 | :: | 
 |  | 
 |  void phy_print_status(struct phy_device *phydev); | 
 |  | 
 | A convenience function to print out the PHY status neatly. | 
 | :: | 
 |  | 
 |  void phy_request_interrupt(struct phy_device *phydev); | 
 |  | 
 | Requests the IRQ for the PHY interrupts. | 
 | :: | 
 |  | 
 |  struct phy_device * phy_attach(struct net_device *dev, const char *phy_id, | 
 | 		                phy_interface_t interface); | 
 |  | 
 | Attaches a network device to a particular PHY, binding the PHY to a generic | 
 | driver if none was found during bus initialization. | 
 | :: | 
 |  | 
 |  int phy_start_aneg(struct phy_device *phydev); | 
 |  | 
 | Using variables inside the phydev structure, either configures advertising | 
 | and resets autonegotiation, or disables autonegotiation, and configures | 
 | forced settings. | 
 | :: | 
 |  | 
 |  static inline int phy_read_status(struct phy_device *phydev); | 
 |  | 
 | Fills the phydev structure with up-to-date information about the current | 
 | settings in the PHY. | 
 | :: | 
 |  | 
 |  int phy_ethtool_ksettings_set(struct phy_device *phydev, | 
 |                                const struct ethtool_link_ksettings *cmd); | 
 |  | 
 | Ethtool convenience functions. | 
 | :: | 
 |  | 
 |  int phy_mii_ioctl(struct phy_device *phydev, | 
 |                    struct mii_ioctl_data *mii_data, int cmd); | 
 |  | 
 | The MII ioctl.  Note that this function will completely screw up the state | 
 | machine if you write registers like BMCR, BMSR, ADVERTISE, etc.  Best to | 
 | use this only to write registers which are not standard, and don't set off | 
 | a renegotiation. | 
 |  | 
 | PHY Device Drivers | 
 | ================== | 
 |  | 
 | With the PHY Abstraction Layer, adding support for new PHYs is | 
 | quite easy. In some cases, no work is required at all! However, | 
 | many PHYs require a little hand-holding to get up-and-running. | 
 |  | 
 | Generic PHY driver | 
 | ------------------ | 
 |  | 
 | If the desired PHY doesn't have any errata, quirks, or special | 
 | features you want to support, then it may be best to not add | 
 | support, and let the PHY Abstraction Layer's Generic PHY Driver | 
 | do all of the work. | 
 |  | 
 | Writing a PHY driver | 
 | -------------------- | 
 |  | 
 | If you do need to write a PHY driver, the first thing to do is | 
 | make sure it can be matched with an appropriate PHY device. | 
 | This is done during bus initialization by reading the device's | 
 | UID (stored in registers 2 and 3), then comparing it to each | 
 | driver's phy_id field by ANDing it with each driver's | 
 | phy_id_mask field.  Also, it needs a name.  Here's an example:: | 
 |  | 
 |    static struct phy_driver dm9161_driver = { | 
 |          .phy_id         = 0x0181b880, | 
 | 	 .name           = "Davicom DM9161E", | 
 | 	 .phy_id_mask    = 0x0ffffff0, | 
 | 	 ... | 
 |    } | 
 |  | 
 | Next, you need to specify what features (speed, duplex, autoneg, | 
 | etc) your PHY device and driver support.  Most PHYs support | 
 | PHY_BASIC_FEATURES, but you can look in include/mii.h for other | 
 | features. | 
 |  | 
 | Each driver consists of a number of function pointers, documented | 
 | in include/linux/phy.h under the phy_driver structure. | 
 |  | 
 | Of these, only config_aneg and read_status are required to be | 
 | assigned by the driver code.  The rest are optional.  Also, it is | 
 | preferred to use the generic phy driver's versions of these two | 
 | functions if at all possible: genphy_read_status and | 
 | genphy_config_aneg.  If this is not possible, it is likely that | 
 | you only need to perform some actions before and after invoking | 
 | these functions, and so your functions will wrap the generic | 
 | ones. | 
 |  | 
 | Feel free to look at the Marvell, Cicada, and Davicom drivers in | 
 | drivers/net/phy/ for examples (the lxt and qsemi drivers have | 
 | not been tested as of this writing). | 
 |  | 
 | The PHY's MMD register accesses are handled by the PAL framework | 
 | by default, but can be overridden by a specific PHY driver if | 
 | required. This could be the case if a PHY was released for | 
 | manufacturing before the MMD PHY register definitions were | 
 | standardized by the IEEE. Most modern PHYs will be able to use | 
 | the generic PAL framework for accessing the PHY's MMD registers. | 
 | An example of such usage is for Energy Efficient Ethernet support, | 
 | implemented in the PAL. This support uses the PAL to access MMD | 
 | registers for EEE query and configuration if the PHY supports | 
 | the IEEE standard access mechanisms, or can use the PHY's specific | 
 | access interfaces if overridden by the specific PHY driver. See | 
 | the Micrel driver in drivers/net/phy/ for an example of how this | 
 | can be implemented. | 
 |  | 
 | Board Fixups | 
 | ============ | 
 |  | 
 | Sometimes the specific interaction between the platform and the PHY requires | 
 | special handling.  For instance, to change where the PHY's clock input is, | 
 | or to add a delay to account for latency issues in the data path.  In order | 
 | to support such contingencies, the PHY Layer allows platform code to register | 
 | fixups to be run when the PHY is brought up (or subsequently reset). | 
 |  | 
 | When the PHY Layer brings up a PHY it checks to see if there are any fixups | 
 | registered for it, matching based on UID (contained in the PHY device's phy_id | 
 | field) and the bus identifier (contained in phydev->dev.bus_id).  Both must | 
 | match, however two constants, PHY_ANY_ID and PHY_ANY_UID, are provided as | 
 | wildcards for the bus ID and UID, respectively. | 
 |  | 
 | When a match is found, the PHY layer will invoke the run function associated | 
 | with the fixup.  This function is passed a pointer to the phy_device of | 
 | interest.  It should therefore only operate on that PHY. | 
 |  | 
 | The platform code can either register the fixup using phy_register_fixup():: | 
 |  | 
 | 	int phy_register_fixup(const char *phy_id, | 
 | 		u32 phy_uid, u32 phy_uid_mask, | 
 | 		int (*run)(struct phy_device *)); | 
 |  | 
 | Or using one of the two stubs, phy_register_fixup_for_uid() and | 
 | phy_register_fixup_for_id():: | 
 |  | 
 |  int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, | 
 | 		int (*run)(struct phy_device *)); | 
 |  int phy_register_fixup_for_id(const char *phy_id, | 
 | 		int (*run)(struct phy_device *)); | 
 |  | 
 | The stubs set one of the two matching criteria, and set the other one to | 
 | match anything. | 
 |  | 
 | When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module load | 
 | time, the module needs to unregister the fixup and free allocated memory when | 
 | it's unloaded. | 
 |  | 
 | Call one of following function before unloading module:: | 
 |  | 
 |  int phy_unregister_fixup(const char *phy_id, u32 phy_uid, u32 phy_uid_mask); | 
 |  int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask); | 
 |  int phy_register_fixup_for_id(const char *phy_id); | 
 |  | 
 | Standards | 
 | ========= | 
 |  | 
 | IEEE Standard 802.3: CSMA/CD Access Method and Physical Layer Specifications, Section Two: | 
 | http://standards.ieee.org/getieee802/download/802.3-2008_section2.pdf | 
 |  | 
 | RGMII v1.3: | 
 | http://web.archive.org/web/20160303212629/http://www.hp.com/rnd/pdfs/RGMIIv1_3.pdf | 
 |  | 
 | RGMII v2.0: | 
 | http://web.archive.org/web/20160303171328/http://www.hp.com/rnd/pdfs/RGMIIv2_0_final_hp.pdf |