\documentclass[aspectratio=169,obeyspaces,spaces,hyphens,dvipsnames]{beamer}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}% http://ctan.org/pkg/lm
\usepackage{minted}
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{pgfplots}
\usepackage{tikz}
\usepackage{tabularx}
\usepackage[normalem]{ulem}

\mode<presentation>
\usetheme{Bootlin}

\def\signed #1{{\leavevmode\unskip\nobreak\hfil\penalty50\hskip2em
  \hbox{}\nobreak\hfil(#1)
  \parfillskip=0pt \finalhyphendemerits=0 \endgraf}}

\graphicspath{ {./images/} }

\newsavebox\mybox
\newenvironment{aquote}[1]
  {\savebox\mybox{#1}\begin{quotation}}
  {\signed{\usebox\mybox}\end{quotation}}

\title{Adding support for PoE}
\authors{Köry Maincent}
\email{kory.maincent@bootlin.com}
\slidesurl{https://bootlin.com/pub/conferences/2024/eoss/maincent-adding-support-for-poe/maincent-adding-support-for-poe.pdf}
\institute{Bootlin}
\conference{ELC Seattle, April 16-18 2024}

\begin{document}

\addtocontents{toc}{\protect\setcounter{tocdepth}{-1}}
\section{Adding support for PoE}
\addtocontents{toc}{\protect\setcounter{tocdepth}{2}}

\begin{frame}{Köry Maincent}
    \begin{itemize}
    \item Embedded Linux engineer at Bootlin
      \begin{itemize}
      \item Embedded Linux, U-Boot, Linux kernel, Yocto, Buildroot {\bf
          expertise}
      \item {\bf Development}, consulting and training
      \item Strong open-source focus
      \end{itemize}
    \item Open-source contributor
    \item Living in {\bf Toulouse}, France
    \end{itemize}
\end{frame}

\begin{frame}{Agenda}
  \begin{itemize}
  \item Introduction to Power over Ethernet
    \begin{itemize}
    \item Principles and advantages
    \item IEEE 802.3 Standards
    \item Hardware description
    \item PSE Basic processes
    \item Power classification and class detection
    \end{itemize}
  \item Adding support for PoE in Linux
    \begin{itemize}
    \item What's existing?
    \item Linux Netlink UAPI
    \item Linux Devicetree Bindings
    \item Usage of regulators framework
    \end{itemize}
  \item Future features in the pipeline
  \end{itemize}
\end{frame}

\section{What is Power over Ethernet}

\begin{frame}{What is Power over Ethernet}
  \begin{columns}
    \column{0.6\textwidth}
    \begin{itemize}
      \item Power a device on twisted Ethernet pairs alongside data
      \item Remove the needs of power cable for Ethernet devices like VoIP Phone, IP Camera, router ...
      \item Power can be applied over 2 Ethernet pairs or 4 Ethernet pairs (PoE4 - 802.3bt standard)
    \end{itemize}
    \column{0.4\textwidth}
    \includegraphics[width=1\textwidth]{phone.jpg}
    \begin{columns}
      \column{0.5\textwidth}
      \includegraphics[width=1\textwidth]{AP.jpg}
      \column{0.5\textwidth}
      \includegraphics[width=1\textwidth]{camera.jpg}
    \end{columns}
  \end{columns}
\end{frame}

\begin{frame}{PoE advantages}
  \begin{columns}
    \column{0.6\textwidth}
    \begin{itemize}
      \item Cost saving: no electricians needed anymore!
      \item Simple and flexible: one cable!
      \item No AC external power needed -> safer and no need for electrical certification!
      \item Reset easily the powered devices
    \end{itemize}
    \column{0.4\textwidth}
    \includegraphics[width=1.1\textwidth]{poe_device.jpg}
  \end{columns}
\end{frame}

\begin{frame}{IEEE 802.3 Standards}
  \begin{itemize}
    \item Clause 33
    \begin{itemize}
      \item Power over 2 Ethernet pairs
      \item IEEE 802.3af-2003
      \begin{itemize}
        \item Power up to 15.4 W
      \end{itemize}
      \item IEEE 802.3at-2009
      \begin{itemize}
        \item Power up to 25.5 W for Type 2 and Class 4 devices
      \end{itemize}
      \item Initially named Power via Media Dependent Interface
      \item Renamed to Power over Ethernet in IEEE 802.3 2022
    \end{itemize}
    \item Clause 145
    \begin{itemize}
      \item Power over 4 Ethernet pairs
      \item IEEE 802.3bt-2018
      \begin{itemize}
        \item Power up to 71.3 W for Type 4 and Class 8 devices
      \end{itemize}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Hardware Power Sourcing Equipment (PSE) description}
  \begin{columns}
    \column{0.7\textwidth}
    \begin{itemize}
      \item Power source over 2/4 Ethernet pairs
      \begin{itemize}
      \item One/two wire pair(s) for source current
      \item One/two wire pair(s) for return current
      \end{itemize}
      \item Ethernet are designed to work over long distance
      \begin{itemize}
        \item Isolation transformers may be used on each pair to avoid disturbance
      \end{itemize}
    \end{itemize}
    \column{0.3\textwidth}
    \includegraphics[width=0.9\textwidth]{pse_hw.jpg}
  \end{columns}
\end{frame}

\begin{frame}{Hardware Powered Devices (PD) description}
  \begin{columns}
    \column{0.7\textwidth}
    \begin{itemize}
      \item Always 4 ports devices to be able to receive power on either pairset in either polarity
      \item {\em Single signature} if bridge outputs are combined, dual signature if separated (less common)
    \end{itemize}
    \column{0.3\textwidth}
    \includegraphics[width=1\textwidth]{pd_hw.jpg}
  \end{columns}
\end{frame}

\begin{frame}{Power Interface (PI) pairsets and polarity}
  \begin{columns}
    \column{0.6\textwidth}
    \begin{itemize}
      \item RJ45 (8P8C)
      \begin{itemize}
        \item 8 connectors -> 4 pairs (4 colors)
        \item Straight-throught cable or Crossover cable
      \end{itemize}
      \begin{onlyenv}<2>
        \item Pairset: one wire pair for source current, one wire pair for return current
        \item 4 configurations possible with PoE2, plus two considering PoE4
        \item Pairsets references to Mode A or Mode B on PD side
      \end{onlyenv}
    \end{itemize}
    \column{0.4\textwidth}
    \begin{onlyenv}<1>
      \includegraphics[width=1\textwidth]{pse_pi.png}
    \end{onlyenv}
    \begin{onlyenv}<2>
      \includegraphics[width=1\textwidth]{polarity.png}
    \end{onlyenv}
  \end{columns}
\end{frame}

\begin{frame}{PSE Basic processes and constraints}
  \begin{itemize}
    \item Ethernet Devices plugged
    \begin{itemize}
      \item Discriminating Powered Devices from other devices that might be damaged if PoE voltages were applied
      \item Assessing the basic power requirements
      \item Conducting mutual discovery and power negotiation
      \item Supporting surge (or inrush) power required to start up the PD
    \end{itemize}
    \item Powered Devices at runtime
    \begin{itemize}
      \item Supporting peak power demands from the PD
      \item Supporting link-layer (LLPD) for specific configurations
      \item Reacting to PD’s that are drawing more power than they should
      \item Supporting unbalanced load currents between pairsets
      \item Limiting maximum possible current for safety
    \end{itemize}
    \item Ethernet Devices unplugged
    \begin{itemize}
      \item Remove power quickly enough
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{PoE detection and classification}
  \begin{columns}
    \column{0.6\textwidth}
    \begin{itemize}
      \item Detection
      \begin{itemize}
        \item Periodic low-voltage pulse between 2.8V and 10V
        \item Measurement of Rdet
      \end{itemize}
      \begin{onlyenv}<2,3>
        \item Classification
        \begin{itemize}
          \item Series of one to five short pulses called “class events” between 15.5V and 20.5V
          \item Current draw variation of the PD on these pulses
          \begin{onlyenv}<3>
            \item One long first class event for Type 3 and 4 PSEs (Class > 4)
          \end{onlyenv}
        \end{itemize}
      \end{onlyenv}
    \end{itemize}
    \column{0.4\textwidth}
    \begin{onlyenv}<1>
      \includegraphics[width=1\textwidth]{detection.png}
    \end{onlyenv}
    \begin{onlyenv}<2>
      \includegraphics[width=1\textwidth]{classification_at.png}
    \end{onlyenv}
    \begin{onlyenv}<3>
      \includegraphics[width=1\textwidth]{classification_bt.png}
    \end{onlyenv}
  \end{columns}
\end{frame}

\begin{frame}{PoE classification pulses}
  \includegraphics[width=1\textwidth]{classification_pulse.png}
\end{frame}

\begin{frame}{PoE classes}
  \includegraphics[width=1\textwidth]{classes.png}
\end{frame}

\section{PoE Linux support}

\begin{frame}{What's existing}
  \begin{itemize}
    \item poed - \url{https://github.com/dentproject/poed}
    \begin{itemize}
      \item Userspace tool written in \code{python}
      \item Need to install \code{python} on the target
      \item Only support pd69200 controller
    \end{itemize}
    \item No generic support of PoE, each constructor has its own example of code
    \item \url{https://www.ti.com/product/TPS23881\#software-development}
  \end{itemize}
\end{frame}

\begin{frame}{State of Linux - Power over Data Line}
  \begin{itemize}
    \item PoDL (IEEE 802.3 clause 30) is like PoE for Single-Pair Ethernet
    \item PoDL was added to Linux at the end of 2022 thanks to Oleksij Rempel
    \item PoDL has similar behavior as PoE in its PSE management
    \begin{itemize}
      \item Core PSE framework support
      \item Netlink UAPI description following the IEEE 802.3 standards
      \item Ethtool PoDL support
    \end{itemize}
    \item Simple PSE PoDL regulator driver and bindings added
  \end{itemize}
\end{frame}

\begin{frame}{Linux support fo PoE}
  \begin{itemize}
    \item PoE development not yet merged mainline, currently in its ninth version
    \item \url{https://lore.kernel.org/r/20240417-feature_poe-v9-0-242293fd1900@bootlin.com}
    \item Adds support for two PSE controller drivers
    \begin{itemize}
      \item Microchip PD692x0
      \item TI TPS23881
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Linux PoE Netlink UAPI}
  \begin{itemize}
    \item Enhance \code{netlink} UAPI with PoE messages following the standards
  \end{itemize}
  \begin{block}{}
    \fontsize{7}{7}\selectfont
    \begin{minted}{C}
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -895,6 +895,9 @@ enum {
        ETHTOOL_A_PODL_PSE_ADMIN_STATE,         /* u32 */
        ETHTOOL_A_PODL_PSE_ADMIN_CONTROL,       /* u32 */
        ETHTOOL_A_PODL_PSE_PW_D_STATUS,         /* u32 */
+       ETHTOOL_A_C33_PSE_ADMIN_STATE,          /* u32 */
+       ETHTOOL_A_C33_PSE_ADMIN_CONTROL,        /* u32 */
+       ETHTOOL_A_C33_PSE_PW_D_STATUS,          /* u32 */

--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
+enum ethtool_c33_pse_admin_state {
+       ETHTOOL_C33_PSE_ADMIN_STATE_UNKNOWN = 1,
+       ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED,
+       ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED,
+};
+
+enum ethtool_c33_pse_pw_d_status {
+       ETHTOOL_C33_PSE_PW_D_STATUS_UNKNOWN = 1,
+       ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED,
+       ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING,
+       ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING,
+       ETHTOOL_C33_PSE_PW_D_STATUS_TEST,
+       ETHTOOL_C33_PSE_PW_D_STATUS_FAULT,
+       ETHTOOL_C33_PSE_PW_D_STATUS_OTHERFAULT,
+};
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Linux PSE PoDL devicetree binding}
  \begin{itemize}
    \item PoDL PI composed by only one pair -> does not need much information
    \item The PSE port number is enough
  \end{itemize}
  \begin{block}{}
    \fontsize{7}{7}\selectfont
    \begin{minted}{dts}
    pse_t1l1: ethernet-pse {
      compatible = "podl-pse-foo-controller";
      pse-supply = <&reg_t1l1>;
      #pse-cells = <1>;
    };

    &ethernet_phy1 {
      pses = <&pse_t1l1 0>;
    }

    &ethernet_phy2 {
      pses = <&pse_t1l1 1>;
    }
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Linux PSE PoE devicetree binding}
  \begin{itemize}
    \item The PoE PI has more information due to the 4 pairs:
    \item PSE Port number, pairset configuration, polarity supported
  \end{itemize}
  \begin{columns}
  \column{0.4\textwidth}
  \begin{block}{}
    \fontsize{7}{7}\selectfont
    \begin{minted}{C}
    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>;
        };
      };
      ...
    \end{minted}
  \end{block}
  \column{0.6\textwidth}
  \begin{block}{}
    \fontsize{6}{6}\selectfont
    \begin{minted}{C}
      ...
      pse-pis {
        #address-cells = <1>;
        #size-cells = <0>;

        pse_pi0: pse-pi@0 {
          reg = <0>;
          #pse-cells = <0>;
          pairset-names = "alternative-a", "alternative-b";
          pairsets = <&phys0>, <&phys1>;
          polarity-supported = "MDI", "S";
          vpwr-supply = <&vpwr>;
        };
        pse_pi1: pse-pi@1 {
          reg = <1>;
          #pse-cells = <0>;
          pairset-names = "alternative-a";
          pairsets = <&phys2>;
          polarity-supported = "MDI";
          vpwr-supply = <&vpwr>;
        };
      };
    };
    &ethernet_phy0 {
      pses = <&pse_pi0>;
    }
    &ethernet_phy1 {
      pses = <&pse_pi1>;
    }
    \end{minted}
  \end{block}
  \end{columns}
\end{frame}

\begin{frame}{Usage of regulator framework}
  \begin{itemize}
    \item PSE is like a regulator but for Ethernet devices
    \item Add code complexity with function wrappers
    \item Benefit from the already written regulator API
    \begin{itemize}
      \item Power limit
      \item Power/voltage status
      \item Temperature limit
      \item Sysfs description
    \end{itemize}
    \item New features like power priorities could also benefit regulator API
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Usage of regulator framework}
  \begin{block}{}
    \fontsize{6}{6}\selectfont
    \begin{minted}{C}
static int
devm_pse_pi_regulator_register(struct pse_controller_dev *pcdev,
                              char *name, int id)
{
...
       rdesc->id = id;
       rdesc->name = name;
       rdesc->type = REGULATOR_CURRENT;
       rdesc->ops = &pse_pi_ops;
       rdesc->owner = pcdev->owner;

       rinit_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
       rinit_data->supply_regulator = "vpwr";

       rconfig.dev = pcdev->dev;
       rconfig.driver_data = pcdev;
       rconfig.init_data = rinit_data;

       rdev = devm_regulator_register(pcdev->dev, rdesc, &rconfig);
...
       pcdev->pi[id].rdev = rdev;

       return 0;
}
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Usage of regulator framework}
  \begin{block}{}
    \fontsize{7}{7}\selectfont
    \begin{minted}{C}
       psec->ps = devm_regulator_get_exclusive(pcdev->dev,
                                               rdev_get_name(pcdev->pi[index].rdev));
       if (IS_ERR(psec->ps)) {
               ret = PTR_ERR(psec->ps);
               goto put_module;
       }

       ret = regulator_is_enabled(psec->ps);
       if (ret < 0)
               goto regulator_put;

       pcdev->pi[index].admin_state_enabled = ret;
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Usage of regulator framework}
  \begin{block}{}
    \fontsize{7}{7}\selectfont
    \begin{minted}{C}
static int pse_ethtool_c33_set_config(struct pse_control *psec,
                                     const struct pse_control_config *config)
{
       int err = 0;

       /* Look at admin_state_enabled status to not call regulator_enable
        * or regulator_disable twice creating a regulator counter mismatch
        */
       switch (config->c33_admin_control) {
       case ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED:
               if (!psec->pcdev->pi[psec->id].admin_state_enabled)
                       err = regulator_enable(psec->ps);
               break;
       case ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED:
               if (psec->pcdev->pi[psec->id].admin_state_enabled)
                       err = regulator_disable(psec->ps);
               break;
       default:
               err = -EOPNOTSUPP;
       }

       return err;
}
    \end{minted}
  \end{block}
\end{frame}


\section{What's next?}

\begin{frame}{Lack of a Linux Ethernet port abstraction}
  \begin{itemize}
    \item Linux current state with this PoE development
    \begin{itemize}
      \item The PHY driver \code{get}s the PSE PI
      \item No way to get a PSE from a Network Interface Card driver
      \item The PSE PIs regulator provider and consumer are currently the same
    \end{itemize}
    \item In reality the PSE PIs are only related to the RJ45 ports
    \item Maxime Chevallier is working on the Linux Ethernet port abstraction
  \end{itemize}
\end{frame}

\begin{frame}{Next features}
  \begin{itemize}
    \item Set and read Power limit
    \item Read power and/or voltage status
    \item Read PoE class
    \item Read failure reason
    \item Configure PSE port priority
    \item Configure persistent configuration
  \end{itemize}
\end{frame}

\section{Demo time!}

\begin{frame}{References}
  \begin{itemize}
    \item References:
    \begin{itemize}
      \item \url{https://community.fs.com/article/power-over-ethernet-tutorial.html}
      \item \url{https://en.wikipedia.org/wiki/Power_over_Ethernet}
      \item \url{https://sifos.com/wp-content/uploads/IEEE-802.3-PoE-Technology-Overview-Sifos-Technologies.pdf}
      \item \url{https://www.poepower.net/}
    \end{itemize}
    \item Sponsored by Dent Project
  \end{itemize}
\end{frame}

\questionslide

\end{document}
