#include <linux/fwnode_mdio.h>
 #include <linux/of.h>
 #include <linux/phy.h>
+#include <linux/pse-pd/pse.h>
 
 MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>");
 MODULE_LICENSE("GPL");
 
+static struct pse_control *
+fwnode_find_pse_control(struct fwnode_handle *fwnode)
+{
+       struct pse_control *psec;
+       struct device_node *np;
+
+       if (!IS_ENABLED(CONFIG_PSE_CONTROLLER))
+               return NULL;
+
+       np = to_of_node(fwnode);
+       if (!np)
+               return NULL;
+
+       psec = of_pse_control_get(np);
+       if (PTR_ERR(psec) == -ENOENT)
+               return NULL;
+
+       return psec;
+}
+
 static struct mii_timestamper *
 fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
 {
                                struct fwnode_handle *child, u32 addr)
 {
        struct mii_timestamper *mii_ts = NULL;
+       struct pse_control *psec = NULL;
        struct phy_device *phy;
        bool is_c45 = false;
        u32 phy_id;
        int rc;
 
+       psec = fwnode_find_pse_control(child);
+       if (IS_ERR(psec))
+               return PTR_ERR(psec);
+
        mii_ts = fwnode_find_mii_timestamper(child);
-       if (IS_ERR(mii_ts))
-               return PTR_ERR(mii_ts);
+       if (IS_ERR(mii_ts)) {
+               rc = PTR_ERR(mii_ts);
+               goto clean_pse;
+       }
 
        rc = fwnode_property_match_string(child, "compatible",
                                          "ethernet-phy-ieee802.3-c45");
                        goto clean_phy;
        }
 
+       phy->psec = psec;
+
        /* phy->mii_ts may already be defined by the PHY driver. A
         * mii_timestamper probed via the device tree will still have
         * precedence.
         */
        if (mii_ts)
                phy->mii_ts = mii_ts;
+
        return 0;
 
 clean_phy:
        phy_device_free(phy);
 clean_mii_ts:
        unregister_mii_timestamper(mii_ts);
+clean_pse:
+       pse_control_put(psec);
 
        return rc;
 }
 
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 #include <linux/phy_led_triggers.h>
+#include <linux/pse-pd/pse.h>
 #include <linux/property.h>
 #include <linux/sfp.h>
 #include <linux/skbuff.h>
 void phy_device_remove(struct phy_device *phydev)
 {
        unregister_mii_timestamper(phydev->mii_ts);
+       pse_control_put(phydev->psec);
 
        device_del(&phydev->mdio.dev);
 
 
  * @master_slave_get: Current master/slave advertisement
  * @master_slave_state: Current master/slave configuration
  * @mii_ts: Pointer to time stamper callbacks
+ * @psec: Pointer to Power Sourcing Equipment control struct
  * @lock:  Mutex for serialization access to PHY
  * @state_queue: Work queue for state machine
  * @shared: Pointer to private data shared by phys in one package
        struct phylink *phylink;
        struct net_device *attached_dev;
        struct mii_timestamper *mii_ts;
+       struct pse_control *psec;
 
        u8 mdix;
        u8 mdix_ctrl;