aboutsummaryrefslogtreecommitdiff
path: root/Documentation/networking/phy.txt
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/networking/phy.txt')
-rw-r--r--Documentation/networking/phy.txt93
1 files changed, 64 insertions, 29 deletions
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
index 29ccae40903..3544c98401f 100644
--- a/Documentation/networking/phy.txt
+++ b/Documentation/networking/phy.txt
@@ -1,7 +1,7 @@
-------
PHY Abstraction Layer
-(Updated 2005-07-21)
+(Updated 2008-04-08)
Purpose
@@ -48,7 +48,7 @@ The MDIO bus
time, so it is safe for them to block, waiting for an interrupt to signal
the operation is complete
- 2) A reset function is necessary. This is used to return the bus to an
+ 2) A reset function is optional. This is used to return the bus to an
initialized state.
3) A probe function is needed. This function should set up anything the bus
@@ -62,7 +62,8 @@ The MDIO bus
5) 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/gianfar_mii.c and arch/ppc/syslib/mpc85xx_devices.c
+ 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/")
Connecting to a PHY
@@ -96,12 +97,13 @@ Letting the PHY Abstraction Layer do Everything
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, "phy0:0", where the first number is the
- bus id, and the second is the PHY's address on that bus.
+ 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, flags);
+ 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
@@ -111,10 +113,16 @@ Letting the PHY Abstraction Layer do Everything
current state, though the PHY will not yet be truly operational at this
point.
- flags is a u32 which can optionally contain phy-specific flags.
+ 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. 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
@@ -172,18 +180,6 @@ Doing it all yourself
A convenience function to print out the PHY status neatly.
- int phy_clear_interrupt(struct phy_device *phydev);
- int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
-
- Clear the PHY's interrupt, and configure which ones are allowed,
- respectively. Currently only supports all on, or all off.
-
- int phy_enable_interrupts(struct phy_device *phydev);
- int phy_disable_interrupts(struct phy_device *phydev);
-
- Functions which enable/disable PHY interrupts, clearing them
- before and after, respectively.
-
int phy_start_interrupts(struct phy_device *phydev);
int phy_stop_interrupts(struct phy_device *phydev);
@@ -191,11 +187,10 @@ Doing it all yourself
start, or disables then frees them for stop.
struct phy_device * phy_attach(struct net_device *dev, const char *phy_id,
- u32 flags);
+ 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. Passes in
- any phy-specific flags as needed.
+ driver if none was found during bus initialization.
int phy_start_aneg(struct phy_device *phydev);
@@ -208,12 +203,6 @@ Doing it all yourself
Fills the phydev structure with up-to-date information about the current
settings in the PHY.
- void phy_sanitize_settings(struct phy_device *phydev)
-
- Resolves differences between currently desired settings, and
- supported settings for the given PHY device. Does not make
- the changes in the hardware, though.
-
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
@@ -264,15 +253,25 @@ Writing a PHY driver
Each driver consists of a number of function pointers:
+ soft_reset: perform a PHY software reset
config_init: configures PHY into a sane state after a reset.
For instance, a Davicom PHY requires descrambling disabled.
- probe: Does any setup needed by the driver
+ probe: Allocate phy->priv, optionally refuse to bind.
+ PHY may not have been reset or had fixups run yet.
suspend/resume: power management
config_aneg: Changes the speed/duplex/negotiation settings
+ aneg_done: Determines the auto-negotiation result
read_status: Reads the current speed/duplex/negotiation settings
ack_interrupt: Clear a pending interrupt
+ did_interrupt: Checks if the PHY generated an interrupt
config_intr: Enable or disable interrupts
remove: Does any driver take-down
+ ts_info: Queries about the HW timestamping status
+ hwtstamp: Set the PHY HW timestamping configuration
+ rxtstamp: Requests a receive timestamp at the PHY level for a 'skb'
+ txtsamp: Requests a transmit timestamp at the PHY level for a 'skb'
+ set_wol: Enable Wake-on-LAN at the PHY level
+ get_wol: Get the Wake-on-LAN status at the PHY level
Of these, only config_aneg and read_status are required to be
assigned by the driver code. The rest are optional. Also, it is
@@ -286,3 +285,39 @@ Writing a PHY driver
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)
+
+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.
+