Introduction
Power over Ethernet (PoE) is a technology that combines power and data transmission over a single Ethernet cable. It simplifies the installation of networked devices like cameras, phones, and wireless access points by eliminating the need for separate power cables. PoE standards define how power is delivered alongside data, ensuring compatibility across devices. Originally denoted as “Power via MDI” (Media Dependent Interface) in the 802.3 IEEE standard, it later evolved into the recognized term “PoE” in the 2022 version of the standard. PoE equipment consists of two key components: Power Sourcing Equipment (PSE) and Powered Devices (PD).
Linux support, DENT initiative
Up until recently, the upstream Linux kernel had absolutely no support for Power over Ethernet technologies. Due to that, every hardware vendor providing PoE hardware was delivering its own vendor-specific and non-standard solution, often centered around not so great user-space libraries, with dubious integration with the rest of the Linux ecosystem and networking stack, like is unfortunately still done quite often by hardware vendors.
The DENT project, which exists under the umbrella of the Linux Foundation, aims at using the Linux Kernel, Switchdev, and other Linux based projects as the basis for building a new standardized network operating system without abstractions or overhead. Among other things supported by DENT is dentOS, a SwitchDev based NOS built on top of Open Network Linux, which includes PoE support, but based on yet another non-standard fully user-space driven solution in the name of poed, where even the HW-specific drivers are implemented in user-space.
So DENT set as a goal to implement a fully upstream solution in the Linux kernel to properly support Power over Ethernet, and contracted Bootlin to perform this development and upstreaming effort.
Previous work
While PoE was not supported in the Linux kernel, in 2022 a PSE (Power Sourcing Equipment) subsystem was added in drivers/net/pse-pd by Oleksij Rempel, with only support for a related technology called Power over Data-Lines (PoDL), standardized by 802.3bu. The work from Oleksij Rempel only supported PoDL, with power provided by a simple regulator provided by the Linux kernel regulator subsystem. As should be the case for any upstream work, we built on top of this existing work to implement for PoE.
Initial support
Our first goal was to bring minimal support for PoE, with only basic features such as enabling/disabling power, and getting the status of a port. In order to prove that our work was generic enough, we set out to implement drivers for two completely different PoE controllers: the Microchip PD692x0 and the TI TPS23881.
Bootlin engineer Köry Maincent conducted this development and its upstreaming, which took no less than 9 iterations, from mid-November 2023 to mid-April 2024:
- version 1, November 16, 2023
- version 2, December 1, 2023
- version 3, February 8, 2024
- version 4, February 15, 2024
- version 5, February 27, 2024
- version 6, March 26, 2024
- version 7, April 9, 2024
- version 8, April 14, 2024
- version 9, April 17, 2024
Our 9th iteration has been merged, and will be part of the upcoming Linux 6.10 release, with the following main commits:
- ethtool: Expand Ethernet Power Equipment with c33 (PoE) alongside PoDL
- net: pse-pd: Introduce PSE types enumeration
- net: ethtool: pse-pd: Expand pse commands with the PSE PoE interface
- netlink: specs: Modify pse attribute prefix
- netlink: specs: Expand the pse netlink command with PoE interface
- MAINTAINERS: Add myself to pse networking maintainer
- net: pse-pd: Add support for PSE PIs
- dt-bindings: net: pse-pd: Add another way of describing several PSE PIs
- net: pse-pd: Add support for setup_pi_matrix callback
- net: pse-pd: Use regulator framework within PSE framework
- dt-bindings: net: pse-pd: Add bindings for PD692x0 PSE controller
- net: pse-pd: Add PD692x0 PSE controller driver
- dt-bindings: net: pse-pd: Add bindings for TPS23881 PSE controller
- net: pse-pd: Add TI TPS23881 PSE controller driver
In the interest of clarity and consistency within the kernel’s networking subsystem, support for PoE is referred to as “c33”. This naming aligns with Clause 33 of the IEEE 802.3 standard, specifically addressing PoE specifications.
Our patch series:
- Extends the existing PSE subsystem to support c33 (PoE), while relying on the same netlink based interface to user-space
- Extends the PSE bindings to add the PSE Power Interface (PI) pairset pinout connection and polarity configuration.
- Uses regulator framework to benefit in the future for already written features like power limit, voltage status and sysfs description.
Together with the Linux kernel side, we contributed to ethtool to have user-space control for PoE. A single commit was needed for the basic support: ethtool: pse-pd: Add support for Power over Ethernet (clause 33)
Here is a minimal example of a Device Tree showing how we hooked up the TI TPS23881 evaluation board, called BOOST-PSEMTHR-007 to an STM32MP157 Discovery Kit, on which we wired only one Ethernet port through the PoE eval board:
&i2c5 { status = "okay"; tps2388:ethernet-pse@20 { compatible = "ti,tps23881"; reg = <0x20>; channels { #address-cells = <1>; #size-cells = <0>; phys0: channel@0 { reg = <0>; }; phys1: channel@1 { reg = <1>; }; phys2: channel@2 { reg = <2>; }; phys3: channel@3 { reg = <3>; }; phys4: channel@5 { reg = <4>; }; phys5: channel@5 { reg = <5>; }; phys6: channel@6 { reg = <6>; }; phys7: channel@7 { reg = <7>; }; }; pse-pis { #address-cells = <1>; #size-cells = <0>; pse_pi0: pse-pi@0 { reg = <0>; #pse-cells = <0>; pairset-names = "alternative-a"; pairsets = <&phys0>; polarity-supported = "MDI"; }; pse_pi1: pse-pi@1 { reg = <1>; #pse-cells = <0>; pairset-names = "alternative-a", "alternative-b"; pairsets = <&phys6 &phys7>; polarity-supported = "MDI", "S"; }; }; }; }; &phy0 { pses = <&pse_pi0>; };
In this Device Tree snippet, we describe the TI TPS23881 chip connected to the I2C5 bus of our system-on-chip. This TPS23881 chip has a total of 8 channels to provide power. In this particular exemple, we describe 2 PSE power interfaces:
pse_pi0
, describes a power interface that uses the single “Alternative A” pair to provide power, using the channelphys0
. This power interface is then described to be used by the single Ethernet interface of our board, through thepses
property of thephy0
node, which is the standard Ethernet PHY Device Tree nodepse_pi1
, describes another power interface that would be used for a two pairs PoE port, where both the “Alternative A” and “Alternative B” pairs are used together to provide power, which is why two channels,phys6
andphys7
are referenced here. The careful reader will notice that thispse_pi1
is not referenced anywhere, as it is indeed not used, and only shown here for illustration purposes
With this in place, one can then control PoE in a completely standard manner using the standard ethtool utility:
# ethtool --show-pse eth0 PSE attributes for eth0: Clause 33 PSE Admin State: disabled Clause 33 PSE Power Detection Status: disabled # ethtool --set-pse eth0 c33-pse-admin-control enable # ethtool --show-pse eth0 PSE attributes for eth0: Clause 33 PSE Admin State: enabled Clause 33 PSE Power Detection Status: delivering power
As is probably obvious from the example, we are able to show the state of the PSE associated to the eth0 network interface, then enable power on this PSE, and show the new state of the PSE.
Improved support
With the initial support merged and included for Linux 6.10, we started working on the next set of features, which include:
- support for several more status information like consumed power, negotiated class and an extended state report
- support for reading and configuring the PoE ports power limit
After its development, this work has gone through 6 iterations on the mailing list:
- version 1, May 29, 2024
- version 2, Jun 7, 2024
- version 3, Jun 14, 2024
- version 4, Jun 25, 2024
- version 5, Jun 28, 2024
- version 6, July 4, 2024
Our 6th iteration was merged very recently, and therefore it is currently in net-next and should become part of Linux 6.11. Here is the full list of commits that have been merged for this improved PoE support:
- net: ethtool: pse-pd: Expand C33 PSE status with class, power and extended state
- netlink: specs: Expand the PSE netlink command with C33 new features
- net: pse-pd: pd692x0: Expand ethtool status message
- net: pse-pd: Add new power limit get and set c33 features
- net: ethtool: Add new power limit get and set features
- netlink: specs: Expand the PSE netlink command with C33 pw-limit attributes
- net: pse-pd: pd692x0: Enhance with new current limit and voltage read callbacks
We still have to submit a few patches against ethtool to provide an easy to use user-space tool for those new features.
Talk at the Embedded Linux Conference
In order to give more details about this work, Köry Maincent gave a talk titled Adding support for PoE at the Embedded Linux Conference in Seattle, in April 2024. See the slides and video below.
Next steps
We are already very proud of these first two steps of PoE supported merged in the upstream Linux kernel, but we have more plans for the coming months, and most notably:
- Support port priority, to define what will happen when the available power is not sufficient to power all devices over PoE, and shutdown the lowest priority devices
- Support the PD62x0 persistent configuration mechanism, so that the PD692x0 retains its custom configuration across reboots
- Modify the poed project to use the new standard Linux interface for PoE, instead of user-space drivers
Of course, do not hesitate to get in touch if you’re a user of PoE, or a provider of PoE hardware. We would definitely be interested in adding support for your use-case or hardware, and expand the upstream Linux kernel support for PoE!