요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=====================
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 (PAL) 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 operated 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_MAC_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_SMII``
This is serial MII, clocked at 125MHz, supporting 100M and 10M speeds.
Some details can be found in
https://opencores.org/ocsvn/smii/smii/trunk/doc/SMII.pdf
``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 as fast
as 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_5GBASER``
This is the IEEE 802.3 Clause 129 defined 5GBASE-R protocol. It is
identical to the 10GBASE-R protocol defined in Clause 49, with the
exception that it operates at half the frequency. Please refer to the
IEEE standard for the definition.
``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.
``PHY_INTERFACE_MODE_25GBASER``
This is the IEEE 802.3 PCS Clause 107 defined 25GBASE-R protocol.
The PCS is identical to 10GBASE-R, i.e. 64B/66B encoded
running 2.5 as fast, giving a fixed bit rate of 25.78125 Gbaud.
Please refer to the IEEE standard for further information.
``PHY_INTERFACE_MODE_100BASEX``
This defines IEEE 802.3 Clause 24. The link operates at a fixed data
rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying
data rate of 100Mpbs.
``PHY_INTERFACE_MODE_QUSGMII``
This defines the Cisco the Quad USGMII mode, which is the Quad variant of
the USGMII (Universal SGMII) link. It's very similar to QSGMII, but uses
a Packet Control Header (PCH) instead of the 7 bytes preamble to carry not
only the port id, but also so-called "extensions". The only documented
extension so-far in the specification is the inclusion of timestamps, for
PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the
same capabilities in terms of link speed and negotiation.
``PHY_INTERFACE_MODE_1000BASEKX``
This is 1000BASE-X as defined by IEEE 802.3 Clause 36 with Clause 73
autonegotiation. Generally, it will be used with a Clause 70 PMD. To
contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this
interface mode has different autonegotiation and only supports full duplex.
``PHY_INTERFACE_MODE_PSGMII``
This is the Penta SGMII mode, it is similar to QSGMII but it combines 5
SGMII lines into a single link compared to 4 on QSGMII.
``PHY_INTERFACE_MODE_10G_QXGMII``
Represents the 10G-QXGMII PHY-MAC interface as defined by the Cisco USXGMII
Multiport Copper Interface document. It supports 4 ports over a 10.3125 GHz
SerDes lane, each port having speeds of 2.5G / 1G / 100M / 10M achieved
through symbol replication. The PCS expects the standard USXGMII code word.
``PHY_INTERFACE_MODE_MIILITE``
Non-standard, simplified MII mode, without TXER, RXER, CRS and COL signals
as defined for the MII. The absence of COL signal makes half-duplex link
modes impossible but does not interfere with BroadR-Reach link modes on
Broadcom (and other two-wire Ethernet) PHYs, because they are full-duplex
only.
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
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
PHY Abstraction Layer의 목적
1-33대부분의 network device는 MAC layer에 interface를 제공하는 register 집합으로 구성됩니다. MAC은 PHY를 통해 실제 연결과 통신합니다. PHY는 보통 Ethernet cable 반대편의 link partner와 link parameter를 협상하고, driver가 선택된 설정을 확인하거나 허용할 설정을 지정할 수 있도록 register interface를 제공합니다.
PHY는 network device와 구별되는 별도 장치이고 register 배치도 표준화되어 있지만, 과거에는 PHY 관리 코드를 network driver 안에 통합하는 관행이 일반적이었습니다. 그 결과 중복 코드가 많이 생겼습니다. 여러 종류의 Ethernet controller가 같은 management bus에 연결되는 embedded system에서는 bus를 안전하게 공유하기도 어렵습니다.
PHY Abstraction Layer(PAL)는 PHY를 device로, PHY에 접근하는 management bus를 실제 bus로 취급합니다. 목표는 코드 재사용과 전체 유지보수성을 높이고, 새 network driver와 새 system의 개발 시간을 줄이는 것입니다. Network driver 작성자가 최소한의 코드로도 완전한 PHY 기능을 사용할 수 있게 하는 공통 interface가 핵심입니다.
PHY 관리 코드를 공통 계층으로 분리하는 이유입니다.
=====================
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 (PAL) 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.
MDIO bus 등록과 driver 의무
34-68대부분의 network device는 management bus로 PHY에 연결됩니다. 장치마다 사용하는 bus가 다를 수 있고 일부는 공통 interface를 공유합니다. PAL을 사용하려면 각 bus interface를 서로 구별되는 device로 등록해야 합니다.
Bus driver는 `write(struct mii_bus *bus, int mii_id, int regnum, u16 value)`와 `read(struct mii_bus *bus, int mii_id, int regnum)`을 구현해야 합니다. `mii_id`는 bus 위 PHY의 주소이고 `regnum`은 register 번호입니다. 두 함수는 interrupt context에서 호출되지 않으므로 작업 완료 interrupt를 기다리며 block해도 안전합니다.
Bus를 초기 상태로 되돌리는 reset 함수는 선택 사항입니다. Probe 함수는 bus driver에 필요한 자원을 준비하고 `mii_bus` 구조체를 설정한 뒤 `mdiobus_register`로 PAL에 등록해야 합니다. Remove 함수는 반대로 `mdiobus_unregister`를 사용해 이 작업을 해제합니다.
일반 driver와 마찬가지로 `device_driver` 구조체를 구성하고 init/exit 함수에서 driver를 등록해야 합니다. Bus 자체도 어딘가에서 device로 선언하고 등록해야 합니다. 구현 예는 `drivers/net/ethernet/freescale/fsl_pq_mdio.c`와 연결된 DTS 파일이며, 원문은 `git grep fsl,.*-mdio arch/powerpc/boot/dts/` 검색 예를 제시합니다.
Bus device 준비부터 PAL 등록과 해제까지의 순서입니다.
필수·선택 callback을 구분합니다.
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/")
RGMII 전기적 지연과 interface 값
69-128RGMII(Reduced Gigabit Medium Independent Interface)는 동기식 125MHz clock과 여러 data line을 사용하는 12-pin 전기 신호 interface입니다. PHY가 data를 정확히 sample할 setup/hold time을 확보하려면 clock line인 RXC 또는 TXC와 data line 사이에 1.5ns에서 2ns의 지연을 넣어야 합니다.
PHY library는 `PHY_INTERFACE_MODE_RGMII*` 값을 제공하여 PHY driver와 필요하면 MAC driver가 지연을 구현하게 합니다. `phy_interface_t` 값은 PHY device 관점에서 해석해야 합니다.
`PHY_INTERFACE_MODE_RGMII`은 PHY가 내부 지연을 넣지 않는다는 뜻입니다. Ethernet MAC이 가능하면 지연을 넣거나 PCB trace가 올바른 1.5~2ns 지연을 제공한다고 가정합니다. `PHY_INTERFACE_MODE_RGMII_TXID`는 PHY가 자신이 처리하는 TXD[3:0] transmit data에 내부 지연을 넣고, `PHY_INTERFACE_MODE_RGMII_RXID`는 RXD[3:0] receive data에 내부 지연을 넣습니다. `PHY_INTERFACE_MODE_RGMII_ID`는 PHY 방향의 transmit과 receive 양쪽 모두에 내부 지연을 넣습니다.
가능하면 PHY 쪽 RGMII 지연을 사용해야 합니다. PHY는 0.5ns, 1.0ns, 1.5ns처럼 sub-nanosecond 단위로 정밀하게 지연을 지정하여 PCB trace 길이 차이를 보정할 수 있습니다. 산업·의료·자동차 등 넓은 환경을 대상으로 검증되므로 온도·압력·전압 변화에도 일정하고 신뢰할 수 있는 지연을 제공합니다. 재사용 가능한 PHYLIB driver가 지연을 정확히 설정하면 비슷한 요구를 가진 더 많은 설계가 올바르게 동작합니다.
PHY가 지연을 제공하지 못하고 MAC driver가 제공할 수 있다면 `phy_interface_t`는 `PHY_INTERFACE_MODE_RGMII`로 두고, PHY 관점에서 필요한 transmit 또는 receive 지연을 MAC에 설정합니다. 반대로 MAC driver가 `phy_interface_t`를 확인한다면 `PHY_INTERFACE_MODE_RGMII` 이외의 mode에서는 MAC-level 지연을 반드시 꺼서 지연이 중복되지 않게 해야 합니다.
MAC과 PHY 모두 필요한 지연을 만들지 못하면 SoC의 pin pad, mux, controller로 pin strength·delay·voltage를 설정해 약 2ns 지연을 넣을 수 있습니다. 또는 serpentine trace처럼 고정 지연을 포함하도록 PCB를 수정할 수 있으며, 이 방법은 software 설정이 필요하지 않을 수 있습니다.
모든 값은 PHY 관점에서 해석합니다.
가능한 한 PHY에 지연을 맡기고 중복 지연을 피합니다.
(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 operated 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.
RGMII 불일치 증상과 PHY 연결 방식
129-168Ethernet MAC과 PHY 사이 RGMII 지연이 맞지 않으면 PHY나 MAC이 신호를 sample할 때 clock과 data가 불안정해집니다. 논리 0과 1을 잘못 복원하여 송수신 데이터가 손상될 수 있습니다.
대표 증상은 송수신이 부분적으로만 동작하면서 packet loss가 자주 또는 간헐적으로 발생하는 것입니다. Ethernet MAC이 들어오는 일부 또는 모든 packet에 FCS/CRC error를 보고하거나 전부 폐기할 수도 있습니다. 10/100Mbit/s처럼 낮은 속도로 바꾸면 setup/hold time 여유가 커져 문제가 사라지는 현상도 지연 불일치의 단서입니다.
Startup 중 network driver는 PHY device와 network device를 연결해야 합니다. 이때 PHY bus와 driver가 모두 load되어 연결할 준비가 끝나 있어야 합니다.
연결 방식은 네 가지입니다. 첫째, PAL이 모든 작업을 처리하고 link state가 바뀔 때만 network driver를 호출합니다. 둘째, interrupt register가 controller에 있는 등의 이유로 interrupt만 network driver가 처리합니다. 셋째, PAL이 대부분 처리하되 매초 driver callback을 먼저 호출하여 PAL보다 먼저 변화에 대응하게 합니다. 넷째, PAL을 함수 library로만 사용하고 network device가 상태 갱신과 PHY 설정 함수를 직접 호출합니다.
자동화 수준에 따른 네 가지 선택입니다.
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
PAL 자동 상태 머신 연결 절차
169-228권장되는 첫 번째 방식에서는 먼저 link state 변화에 반응하는 `static void adjust_link(struct net_device *dev)` 함수를 준비합니다. 다음으로 연결할 PHY의 device name을 알아야 합니다. 이름은 보통 `0:00`처럼 bus ID와 그 bus 위 PHY 주소로 구성되며, bus가 자신의 ID를 고유하게 만듭니다.
`phydev = phy_connect(dev, phy_name, &adjust_link, interface)`를 호출하면 network device를 PHY에 연결합니다. 반환값 `phydev`는 PHY를 나타내는 `struct phy_device` 포인터입니다. 성공하면 software state machine이 시작되고 PHY interrupt가 있으면 등록됩니다. 현재 상태 정보도 채워지지만 이 시점에는 아직 PHY가 완전히 동작하는 것은 아닙니다.
Hardware 제약처럼 PHY가 알아야 할 board별 조건은 `phy_connect()` 전에 `phydev->dev_flags`에 PHY-specific flag로 설정해야 합니다. 그러면 하위 PHY driver가 flag를 검사해 필요한 특수 작업을 수행할 수 있습니다.
`interface`는 controller와 PHY 사이 연결 종류를 지정하며 GMII, MII, RGMII, SGMII 등이 있습니다. 전체 목록은 `include/linux/phy.h`에 있습니다.
Controller가 지원하지 않는 mode는 `phydev->supported`와 `phydev->advertising`에서 제거해야 합니다. 예를 들어 10/100 controller가 Gigabit PHY에 연결되면 `SUPPORTED_1000baseT*`를 mask off합니다. Bitfield 정의는 `include/linux/ethtool.h`에 있습니다. `SUPPORTED_Pause`와 `SUPPORTED_AsymPause`를 제외하고 새 bit를 설정하면 PHY가 지원하지 않는 상태에 들어갈 수 있으므로, 일반적으로 bit를 추가해서는 안 됩니다.
Controller가 traffic을 처리할 준비가 되면 `phy_start(phydev)`를 호출합니다. MAC interrupt가 PHY 상태 변화도 처리한다면 호출 전에 `phydev->irq = PHY_MAC_INTERRUPT`로 설정하고 network driver에서 `phy_mac_interrupt()`를 사용합니다. Interrupt를 쓰지 않으려면 `phydev->irq = PHY_POLL`로 설정합니다. `phy_start()`는 해당하는 PHY interrupt를 활성화하고 phylib state machine을 시작합니다.
Network 연결을 잠시라도 끊을 때는 `phy_stop(phydev)`을 호출합니다. 이 함수는 phylib state machine을 중지하고 PHY interrupt도 비활성화합니다.
PHY 연결 준비부터 traffic 시작과 중지까지의 호출 순서입니다.
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_MAC_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 mode의 의미
229-342`phy_connect()` 계열 함수에 전달하는 PHY interface mode는 PHY interface의 초기 동작 mode를 정의합니다. 협상 결과에 따라 software 개입 없이 interface mode를 동적으로 바꾸는 PHY도 있으므로 이 값이 계속 일정하다고 보장되지는 않습니다.
`PHY_INTERFACE_MODE_SMII`는 125MHz로 clock되는 serial MII이며 100M과 10M 속도를 지원합니다. 원문은 OpenCores의 SMII PDF를 세부 참고 자료로 연결합니다.
`PHY_INTERFACE_MODE_1000BASEX`는 IEEE 802.3 clause 36의 single-lane SerDes link입니다. 10B/8B encoding으로 고정 1.25Gbaud에서 동작하여 실제 data rate는 1Gbps입니다. Data stream의 16-bit control word가 상대와 duplex 및 pause mode를 협상합니다. 2.5Gbps처럼 clock을 높인 variant는 포함하지 않습니다.
`PHY_INTERFACE_MODE_2500BASEX`는 1000BASE-X를 표준보다 2.5배 빠르게 clock하여 고정 3.125Gbaud로 동작하는 variant입니다.
`PHY_INTERFACE_MODE_SGMII`는 Cisco SGMII로, IEEE 802.3의 1000BASE-X를 변형한 것입니다. 단일 SerDes lane이 10B/8B encoding과 고정 1.25Gbaud로 동작합니다. 기본 data rate는 1Gbps이고 100Mbps와 10Mbps는 각 data symbol을 반복하여 만듭니다. 802.3 control word는 PHY가 협상한 speed·duplex를 MAC에 보내고 MAC이 수신을 확인하는 용도로 재사용됩니다. 2.5Gbps up-clocked variant는 포함하지 않습니다.
SGMII와 1000BASE-X 설정이 서로 맞지 않아도 일부 환경에서는 data가 통과할 수 있습니다. 하지만 16-bit control word 해석이 달라 duplex, pause 또는 다른 설정이 어긋날 수 있으며 결과는 MAC과 PHY 동작에 좌우됩니다.
`PHY_INTERFACE_MODE_5GBASER`는 IEEE 802.3 clause 129의 5GBASE-R이며 clause 49의 10GBASE-R과 같지만 절반 주파수로 동작합니다. `PHY_INTERFACE_MODE_10GBASER`는 여러 medium에 사용하는 clause 49의 10GBASE-R입니다. XFI와 SFI는 단일 SERDES lane에서 여러 protocol을 허용하고 signal의 전기적 특성도 정의하므로 그 자체가 PHY interface type은 아닙니다.
`PHY_INTERFACE_MODE_10GKR`는 clause 49의 10GBASE-R에 clause 73 autonegotiation을 결합합니다. Legacy 사용 때문에 일부 10GBASE-R 코드가 이 정의를 잘못 사용하는 경우가 있습니다.
`PHY_INTERFACE_MODE_25GBASER`는 IEEE 802.3 PCS clause 107의 25GBASE-R입니다. PCS는 10GBASE-R과 같은 64B/66B encoding을 사용하지만 2.5배 빠르게 동작하여 고정 25.78125Gbaud를 냅니다.
`PHY_INTERFACE_MODE_100BASEX`는 IEEE 802.3 clause 24를 정의합니다. 4B/5B encoding으로 고정 125Mbps line rate에서 동작하여 실제 data rate는 100Mbps입니다. 원문에는 두 수치의 단위가 `Mpbs`로 적혀 있으며 원문 영역에는 그대로 보존됩니다.
`PHY_INTERFACE_MODE_QUSGMII`는 Cisco Quad USGMII mode입니다. QSGMII와 비슷하지만 7-byte preamble 대신 Packet Control Header(PCH)를 사용하여 port ID와 extension을 전달합니다. 현재 문서화된 extension은 PTP PHY를 위한 timestamp 포함입니다. QSGMII와 호환되지는 않지만 link speed와 negotiation 능력은 같습니다.
`PHY_INTERFACE_MODE_1000BASEKX`는 clause 36의 1000BASE-X에 clause 73 autonegotiation을 결합하며 일반적으로 clause 70 PMD와 함께 사용합니다. Clause 38·39 PMD용 1000BASE-X PHY mode와 달리 autonegotiation 방식이 다르고 full duplex만 지원합니다.
`PHY_INTERFACE_MODE_PSGMII`는 Penta SGMII입니다. QSGMII가 네 SGMII line을 하나로 결합하는 것과 비슷하지만 다섯 line을 결합합니다.
`PHY_INTERFACE_MODE_10G_QXGMII`는 Cisco USXGMII Multiport Copper Interface 문서가 정의한 10G-QXGMII PHY-MAC interface입니다. 10.3125GHz SerDes lane 하나로 port 네 개를 지원하며, 각 port는 symbol replication으로 2.5G·1G·100M·10M을 제공합니다. PCS는 표준 USXGMII code word를 기대합니다.
`PHY_INTERFACE_MODE_MIILITE`는 표준 MII의 TXER, RXER, CRS, COL signal을 생략한 비표준 간소화 MII mode입니다. COL이 없으므로 half-duplex link mode는 사용할 수 없습니다. 다만 Broadcom과 그 밖의 two-wire Ethernet PHY에서 쓰는 BroadR-Reach mode는 full-duplex 전용이므로 방해받지 않습니다.
속도, encoding, 협상 특성을 비교합니다.
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_SMII``
This is serial MII, clocked at 125MHz, supporting 100M and 10M speeds.
Some details can be found in
https://opencores.org/ocsvn/smii/smii/trunk/doc/SMII.pdf
``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 as fast
as 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_5GBASER``
This is the IEEE 802.3 Clause 129 defined 5GBASE-R protocol. It is
identical to the 10GBASE-R protocol defined in Clause 49, with the
exception that it operates at half the frequency. Please refer to the
IEEE standard for the definition.
``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.
``PHY_INTERFACE_MODE_25GBASER``
This is the IEEE 802.3 PCS Clause 107 defined 25GBASE-R protocol.
The PCS is identical to 10GBASE-R, i.e. 64B/66B encoded
running 2.5 as fast, giving a fixed bit rate of 25.78125 Gbaud.
Please refer to the IEEE standard for further information.
``PHY_INTERFACE_MODE_100BASEX``
This defines IEEE 802.3 Clause 24. The link operates at a fixed data
rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying
data rate of 100Mpbs.
``PHY_INTERFACE_MODE_QUSGMII``
This defines the Cisco the Quad USGMII mode, which is the Quad variant of
the USGMII (Universal SGMII) link. It's very similar to QSGMII, but uses
a Packet Control Header (PCH) instead of the 7 bytes preamble to carry not
only the port id, but also so-called "extensions". The only documented
extension so-far in the specification is the inclusion of timestamps, for
PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the
same capabilities in terms of link speed and negotiation.
``PHY_INTERFACE_MODE_1000BASEKX``
This is 1000BASE-X as defined by IEEE 802.3 Clause 36 with Clause 73
autonegotiation. Generally, it will be used with a Clause 70 PMD. To
contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this
interface mode has different autonegotiation and only supports full duplex.
``PHY_INTERFACE_MODE_PSGMII``
This is the Penta SGMII mode, it is similar to QSGMII but it combines 5
SGMII lines into a single link compared to 4 on QSGMII.
``PHY_INTERFACE_MODE_10G_QXGMII``
Represents the 10G-QXGMII PHY-MAC interface as defined by the Cisco USXGMII
Multiport Copper Interface document. It supports 4 ports over a 10.3125 GHz
SerDes lane, each port having speeds of 2.5G / 1G / 100M / 10M achieved
through symbol replication. The PCS expects the standard USXGMII code word.
``PHY_INTERFACE_MODE_MIILITE``
Non-standard, simplified MII mode, without TXER, RXER, CRS and COL signals
as defined for the MII. The absence of COL signal makes half-duplex link
modes impossible but does not interfere with BroadR-Reach link modes on
Broadcom (and other two-wire Ethernet) PHYs, because they are full-duplex
only.
Pause frame과 PAL 보조 callback
343-371PHY는 flow control이나 pause frame 생성에 직접 참여하지 않습니다. 다만 Ethernet MAC controller가 해당 기능을 지원한다는 사실을 link partner에 알리도록 `MII_ADVERTISE`의 `SUPPORTED_Pause`와 `SUPPORTED_AsymPause` bit가 설정되게 합니다.
Pause frame 생성은 Ethernet MAC driver의 역할이므로, MAC driver가 두 bit를 적절히 설정해 advertisement와 지원 여부를 표시하는 것이 권장됩니다. 설정은 `phy_connect()` 전이나 후에 할 수 있고, ethtool의 `set_pauseparam` 기능 구현 결과로 처리할 수도 있습니다.
PAL의 내장 state machine이 network device와 PHY를 동기화하는 데 도움이 필요하면 PHY 연결 때 helper function을 등록할 수 있습니다. 이 함수는 state machine이 변화에 반응하기 전 매초 호출됩니다. `phy_attach()`와 `phy_prepare_link()`를 직접 호출한 뒤 `phy_start_machine()`의 두 번째 인수에 특수 handler를 전달합니다.
원문 작성 시점에는 이 기능의 사용 예가 없고, 작성자가 사용하는 driver는 모두 완전 자동 방식이라 시험도 제한적입니다. 따라서 이 경로는 충분한 검증을 전제로 사용해야 합니다.
매초 driver handler가 먼저 실행된 뒤 PAL state machine이 반응합니다.
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.
상태 머신 없이 직접 제어하는 API
372-440PAL state machine이 PHY와 network device의 복잡한 상호작용을 추적할 수 없는 드문 경우에는 `phy_attach()`만 호출하고 `phy_start_machine()`이나 `phy_prepare_link()`를 호출하지 않을 수 있습니다. 그러면 `phydev->state`를 driver가 전적으로 관리합니다. `phy_start()`와 `phy_stop()`도 일부 state를 바꾸므로 피해야 할 수 있습니다.
State machine 없이도 유용한 기능에 접근할 수 있게 설계되었고, 많은 함수는 복잡한 state machine 이전의 함수에서 유래했습니다. 그러나 이 방식 역시 원문 작성 시점에 시험되지 않았으므로 주의가 필요합니다.
`phy_read()`와 `phy_write()`는 단순 register read/write primitive이며 bus의 read/write function pointer를 호출합니다. `phy_print_status()`는 PHY 상태를 보기 좋게 출력하고, `phy_request_interrupt()`는 PHY interrupt의 IRQ를 요청합니다.
`phy_attach()`는 network device를 특정 PHY에 연결합니다. Bus 초기화 때 적절한 PHY driver를 찾지 못했다면 generic driver에 bind합니다.
`phy_start_aneg()`는 `phydev` 내부 변수에 따라 advertisement를 구성하고 autonegotiation을 다시 시작하거나, autonegotiation을 끄고 강제 설정을 적용합니다. `phy_read_status()`는 PHY의 현재 설정을 읽어 최신 정보로 `phydev`를 채웁니다.
`phy_ethtool_ksettings_set()`은 ethtool 설정을 위한 편의 함수입니다. `phy_mii_ioctl()`은 MII ioctl을 처리하지만 `BMCR`, `BMSR`, `ADVERTISE` 같은 표준 register를 쓰면 state machine을 완전히 깨뜨릴 수 있습니다. 재협상을 유발하지 않는 비표준 register 쓰기에만 사용하는 것이 좋습니다.
State machine을 직접 관리할 때 사용할 핵심 API입니다.
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.
Generic PHY와 전용 PHY driver 작성
441-507PAL을 사용하면 새 PHY 지원을 쉽게 추가할 수 있습니다. Errata, quirk, 지원해야 할 특수 기능이 없다면 별도 driver를 추가하지 않고 PAL의 Generic PHY Driver에 맡기는 편이 좋습니다.
전용 PHY driver가 필요하면 먼저 올바른 PHY device와 match되게 해야 합니다. Bus 초기화 중 register 2와 3에 저장된 device UID를 읽고, 각 driver의 `phy_id`를 `phy_id_mask`와 AND한 값과 비교합니다. Driver에는 이름도 필요합니다. 원문의 `dm9161_driver` 예는 `phy_id = 0x0181b880`, 이름 `Davicom DM9161E`, `phy_id_mask = 0x0ffffff0`을 사용합니다.
그다음 PHY device와 driver가 지원하는 speed, duplex, autonegotiation 등의 feature를 지정합니다. 대부분은 `PHY_BASIC_FEATURES`를 지원하며 다른 feature는 `include/mii.h`에서 확인할 수 있습니다.
각 driver는 `include/linux/phy.h`의 `struct phy_driver`에 문서화된 function pointer로 구성됩니다. Driver 코드가 반드시 지정해야 하는 것은 `config_aneg`와 `read_status`뿐이고 나머지는 선택 사항입니다.
가능하면 두 필드에도 generic PHY driver의 `genphy_config_aneg`와 `genphy_read_status`를 사용하는 것이 좋습니다. 직접 구현해야 하더라도 보통 generic 함수를 호출하기 전후에 특수 작업만 추가하는 wrapper면 충분합니다. 예제는 `drivers/net/phy/`의 Marvell, Cicada, Davicom driver에서 찾을 수 있습니다. 원문 작성 시점에는 lxt와 qsemi driver가 시험되지 않았다고 명시합니다.
PHY의 MMD register 접근은 기본적으로 PAL이 처리하지만 필요하면 특정 PHY driver가 override할 수 있습니다. IEEE가 MMD register 정의를 표준화하기 전에 제조된 PHY가 그런 사례입니다. 현대 PHY 대부분은 generic PAL 접근을 사용할 수 있습니다.
PAL의 Energy Efficient Ethernet(EEE) 지원도 MMD 접근을 사용합니다. PHY가 IEEE 표준 접근을 지원하면 PAL이 EEE 조회와 설정을 위해 MMD register에 접근하고, 전용 driver가 override했다면 PHY-specific interface를 사용합니다. 구현 예는 `drivers/net/phy/`의 Micrel driver입니다.
Generic driver 우선 원칙과 전용 driver match 절차입니다.
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.
Platform별 board fixup 등록
508-553Platform과 PHY의 특정 조합에는 별도 처리가 필요할 수 있습니다. 예를 들어 PHY clock input 위치를 바꾸거나 data path latency를 보정하는 지연을 추가해야 할 수 있습니다. PHY Layer는 PHY를 올리거나 나중에 reset할 때 실행할 fixup을 platform code가 등록할 수 있게 합니다.
PHY를 시작할 때 등록된 fixup 가운데 PHY device의 `phy_id`에 든 UID와 `phydev->dev.bus_id`에 든 bus identifier가 모두 일치하는 항목을 찾습니다. `PHY_ANY_ID`와 `PHY_ANY_UID`는 각각 bus ID와 UID를 무엇이든 match시키는 wildcard입니다.
Match를 찾으면 PHY layer가 해당 fixup의 run function을 호출합니다. 함수에는 대상 `phy_device` 포인터가 전달되므로 반드시 그 PHY에 대해서만 작업해야 합니다.
Platform code는 `phy_register_fixup()`으로 bus ID, UID, UID mask, run callback을 모두 지정할 수 있습니다. `phy_register_fixup_for_uid()`와 `phy_register_fixup_for_id()` stub을 사용하면 한 match 기준을 지정하고 다른 기준은 모든 값과 일치하게 설정합니다.
Module load 때 `phy_register_fixup()` 또는 `_for_uid()`·`_for_id()`를 호출했다면 unload 전에 fixup을 unregister하고 할당한 memory를 해제해야 합니다. 원문은 `phy_unregister_fixup`, `phy_unregister_fixup_for_uid`, `phy_register_fixup_for_id` prototype을 나열합니다. 마지막 이름은 unregister 절에서 `register`로 적혀 있으며 원문 code block에는 그대로 보존했습니다.
UID와 bus ID 기준 및 wildcard를 정리합니다.
Module이 등록한 fixup은 unload 전에 반드시 해제합니다.
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);
관련 IEEE와 RGMII 표준
554-564관련 표준으로 IEEE 802.3의 CSMA/CD access method 및 physical layer specification section two가 제시됩니다. 원문은 IEEE의 802.3-2008 section 2 PDF 주소를 포함합니다.
RGMII 전기 interface와 timing은 RGMII v1.3 및 v2.0 문서에서 확인할 수 있습니다. 두 문서의 원래 HP 주소는 Web Archive snapshot으로 연결되어 있으며 URL은 원문 그대로 보존됩니다.
문서 끝에 제시된 규격입니다.
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
요약·해설
phy.rst:1-564PHY Abstraction Layer는 MAC driver에서 중복되던 PHY와 management bus 관리를 PHYLIB 공통 계층으로 분리합니다. MDIO 등록부터 RGMII timing, 자동·수동 link state 관리, SerDes interface mode, 전용 PHY driver와 board fixup까지 PHY 수명 주기 전체를 다룹니다.
Platform bus에서 사용자 설정까지의 주요 객체와 제어 흐름입니다.