The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
In Linux, “PHY Framework” usually means the Generic PHY Framework, documented in the kernel as the PHY subsystem. It is an in-kernel interface for separately managed physical-layer hardware used by controllers such as USB, Ethernet, SATA, PCIe, and wireless devices. A PHY provider driver owns clocks, resets, regulators, calibration, and hardware sequencing; a consumer controller obtains a struct phy and uses common lifecycle APIs.
The framework is most useful when the physical-layer block is a distinct device or reusable hardware resource. If the PHY logic is inseparably integrated into a controller, a separate generic PHY driver may add no value. “PHY” is also overloaded in Linux: Ethernet transceivers and some SerDes or wireless components can use subsystem-specific abstractions instead.
What a PHY does
PHY means physical layer. It performs the electrical and low-level protocol work needed to connect a digital controller to a transmission medium, including serialization and deserialization, encoding and decoding, rate generation, lane configuration, calibration, and link-related analog operation. USB, Ethernet, SATA, PCIe, and wireless hardware are common examples of systems that may depend on a PHY.
An external PHY is a separately managed chip or hardware block. An integrated PHY is built into the controller. The generic framework is primarily aimed at the former: it creates a clean boundary between the controller driver and physical-layer implementation.
#1 Best Overall
The provider/consumer architecture
Peripheral controller driver
|
| generic PHY consumer API
v
struct phy
|
v
PHY provider driver
|
v
PHY hardware
The provider creates one or more PHY instances and implements hardware-specific operations. The consumer discovers a PHY, initializes it, powers it, selects a mode when required, and later unwinds those actions. The framework standardizes discovery and lifecycle; it does not make unrelated PHYs interchangeable or remove the need for vendor-specific register programming.
Historically, PHY drivers were spread among controller or subsystem code. The generic interface improves reuse and maintainability by allowing a PHY implementation to serve different consumers while keeping analog details, power sequencing, and quirks in one provider driver. See the Linux PHY subsystem documentation.
When to use it—and when not to
- Use the generic framework when a distinct PHY block has its own clocks, supplies, reset, calibration, mode, or power lifecycle.
- It is especially useful when multiple controllers can consume the block or when the controller and PHY should be maintained independently.
- A separate framework may be unnecessary when the physical layer is inseparable from the controller and no provider/consumer boundary exists.
- Do not assume every Ethernet transceiver belongs here: Ethernet PHY management commonly uses an Ethernet-specific subsystem. Check the hardware’s existing kernel abstraction and binding.
Writing a provider driver
Define operations and create the PHY
A provider supplies a struct phy_ops. Common callbacks include init, exit, power_on, power_off, set_mode, and, where supported, set_mode_ext. A callback is optional in the implementation; consumers should nevertheless use the standard initialization and power APIs so the same controller works with PHYs that implement them.
Recommended Free Tools
static const struct phy_ops my_phy_ops = {
.init = my_phy_init,
.exit = my_phy_exit,
.power_on = my_phy_power_on,
.power_off = my_phy_power_off,
.set_mode = my_phy_set_mode,
.owner = THIS_MODULE,
};
phy = devm_phy_create(dev, child_np, &my_phy_ops);
if (IS_ERR(phy))
return PTR_ERR(phy);
phy_set_drvdata(phy, priv);
The documented constructors are phy_create() and devm_phy_create(). Device-managed creation is normally preferable when the PHY lifetime follows the provider device. Store private state with phy_set_drvdata() and retrieve it in callbacks with phy_get_drvdata().
Register the provider
For Device Tree consumers, register a provider after creating its PHY instances:
Rank #2
devm_of_phy_provider_register(dev, my_of_xlate);
The non-managed form is of_phy_provider_register(). Current kernels also provide of_phy_provider_register_full() and its managed variant for bindings whose PHY child nodes are nested below additional levels.
A single- PHY provider can often use of_phy_simple_xlate. A provider with several instances generally needs an of_xlate function that validates the firmware specifier and returns the correct PHY. Reject invalid indices rather than silently returning another lane.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteMultiple instances
Multiple PHYs make firmware translation part of the driver contract. Validate the binding’s #phy-cells, phandle arguments, child-node layout, and index range. The provider’s compatible string and binding schema—not the generic framework—define the exact representation.
Writing a consumer driver
Acquire the reference
Consumers can use name-based, Device Tree, or index-based helpers:
struct phy *phy_get(struct device *dev, const char *string);
struct phy *devm_phy_get(struct device *dev, const char *string);
struct phy *devm_phy_optional_get(struct device *dev, const char *string);
struct phy *devm_of_phy_get_by_index(struct device *dev,
struct device_node *np, int index);
Other documented helpers include devm_of_phy_get() and devm_of_phy_optional_get(). The devm_ variants release references automatically at device teardown. Name-based calls use a connection identifier; index-based calls are convenient for controllers with several PHYs. In Device Tree, names normally correspond to phy-names.
Rank #3
- Mastering Linux Device Driver Development: Write custom device drivers to support computer peripherals in Linux operating systems
- ABIS BOOK
- Packt Publishing
Required versus optional PHYs
Use an optional-get function only when the hardware genuinely supports operation without that PHY:
phy = devm_phy_optional_get(dev, "usb");
if (IS_ERR(phy))
return PTR_ERR(phy);
/* phy == NULL is valid for an absent optional PHY. */
Do not convert NULL into -ENODEV unconditionally. The optional APIs return NULL for an absent PHY, while real lookup failures remain encoded errors checked with IS_ERR(). The documented consumer operations—including initialization, exit, power, and release—are no-ops for a NULL PHY.
Follow the lifecycle order
The documented sequence is:
[devm_][of_]phy_get()
phy_init()
phy_power_on()
[phy_set_mode[_ext]()]
...
phy_power_off()
phy_exit()
[[of_]phy_put()]
A representative probe path is:
phy = devm_phy_get(dev, "usb");
if (IS_ERR(phy))
return PTR_ERR(phy);
ret = phy_init(phy);
if (ret)
return ret;
ret = phy_power_on(phy);
if (ret) {
phy_exit(phy);
return ret;
}
ret = phy_set_mode(phy, PHY_MODE_USB_HOST);
if (ret) {
phy_power_off(phy);
phy_exit(phy);
return ret;
}
/* Configure and start the controller. */
On shutdown, runtime suspend, or an equivalent stop path, stop controller traffic first, then call phy_power_off() and phy_exit(). If references were acquired manually, finish with phy_put(); managed references are released automatically. The exact mode constant depends on the consumer and kernel headers, and not every PHY accepts every enum phy_mode.
Device Tree integration
A consumer usually references a provider with phys and names connections with phy-names:
usb@... {
phys = <&usb2_phy>;
phy-names = "usb2-phy";
};
controller@... {
phys = <&phy_provider 0>, <&phy_provider 1>;
phy-names = "usb2", "usb3";
};
These snippets are illustrative, not universal bindings. The individual device schema defines the compatible string, node hierarchy, #phy-cells, phandle arguments, and whether child nodes are required. Validate the binding with the kernel’s schema tooling and match the provider’s translation logic to it.
Rank #4
Non-Device-Tree lookup mappings
Platforms without a Device Tree phandle model can associate a consumer with a PHY explicitly:
int phy_create_lookup(struct phy *phy,
const char *con_id,
const char *dev_id);
void phy_remove_lookup(struct phy *phy,
const char *con_id,
const char *dev_id);
This is relevant to ACPI or platform descriptions, legacy board files, and statically described devices. When a standard firmware binding exists, use it rather than adding new ad-hoc lookup tables.
Runtime power management and hardware sequencing
Creating a PHY enables runtime PM for its device; destroying it disables runtime PM. The PHY device is a child of the provider device, allowing parent-child runtime-PM relationships to propagate. phy_power_on() and phy_power_off() participate in that lifecycle, but they do not replace provider-specific sequencing.
A real provider may need ordered regulators, reference and functional clocks, reset deassertion, power-domain transitions, calibration, PLL-lock polling, lane selection, firmware tables, and silicon-revision workarounds. Coordinate runtime and system suspend with the controller: powering down a PHY while its controller still accesses it can cause link loss, USB errors, PCIe instability, or resume failures. Resume may require restoring registers and repeating initialization before the controller touches the link.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
API quick reference
| Purpose | Representative APIs |
|---|---|
| Create a PHY | phy_create(), devm_phy_create() |
| Attach private data | phy_set_drvdata(), phy_get_drvdata() |
| Register provider | of_phy_provider_register(), devm_of_phy_provider_register() |
| Acquire consumer reference | phy_get(), devm_phy_get(), optional and Device Tree helpers |
| Lifecycle | phy_init(), phy_power_on(), phy_power_off(), phy_exit() |
| Mode | phy_set_mode(), phy_set_mode_ext() |
| Non-DT mapping | phy_create_lookup(), phy_remove_lookup() |
| Destroy or release | phy_destroy(), devm_phy_destroy(), phy_put() |
Troubleshooting by symptom
Probe returns -EPROBE_DEFER
- Confirm the provider node is enabled and its compatible value matches a loaded driver.
- Check the consumer’s
phys,phy-names, and phandle arguments. - Inspect provider probe logs and verify that PHY creation and provider registration complete.
- Check regulator, clock, reset, power-domain, and firmware dependencies.
Missing PHY or -ENODEV
Decide whether the PHY is required. For an optional design, use an optional-get API and accept NULL. Otherwise inspect the connection name, index ordering, provider node, and binding.
Best Value
Power-on succeeds but the link fails
Check mode selection, reference-clock rate, reset order, supply stability, lane/protocol agreement, calibration, PLL-lock waits, and unexpected runtime suspension. A successful API return does not prove that the analog link is correctly configured.
Suspend or resume fails
Ensure the controller stops using the link before phy_power_off(), and that resume restores provider state before controller access. Verify parent-child runtime-PM ordering and any registers lost during power collapse.
Provider removal or module unload fails
Stop active transfers, ensure consumers have released references, and never destroy a PHY that is still in use. Avoid mixing manual and device-managed cleanup in a way that causes double release or ordering conflicts.
Bottom line
Linux’s Generic PHY Framework standardizes how a controller discovers and operates a separately managed physical-layer block. A robust implementation gets the provider/consumer boundary, firmware translation, required-versus-optional handling, lifecycle order, and runtime-PM dependencies right. The framework supplies the common plumbing; the provider remains responsible for the electrical and hardware-specific details.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

