Add required changes to call PCS function to configure the Serdes Port.
The Ethernet driver is adapted following Upstream Kernel node structure.

Function calling order is the same of Phylink upstream kernel.

Signed-off-by: Christian Marangi <ansuels...@gmail.com>
---
 drivers/net/Kconfig      |  1 +
 drivers/net/airoha_eth.c | 89 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f73dafa7d09..e0e426204ce 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -129,6 +129,7 @@ config AIROHA_ETH
        select PHYLIB
        select DM_RESET
        select MDIO_MT7531
+       select PCS_AIROHA_AN7581
        help
          This Driver support Airoha Ethernet QDMA Driver
          Say Y to enable support for the Airoha Ethernet QDMA.
diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c
index 6be6ec2845b..9bd5123ba05 100644
--- a/drivers/net/airoha_eth.c
+++ b/drivers/net/airoha_eth.c
@@ -18,10 +18,13 @@
 #include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/ethtool.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/time.h>
 
+#include "airoha/pcs-airoha.h"
+
 #define AIROHA_MAX_NUM_GDM_PORTS       1
 #define AIROHA_MAX_NUM_QDMA            1
 #define AIROHA_MAX_NUM_RSTS            3
@@ -645,9 +648,71 @@ static int airoha_qdma_init(struct udevice *dev,
        return airoha_qdma_hw_init(qdma);
 }
 
+static int airoha_pcs_init(struct udevice *dev, ofnode node)
+{
+       struct airoha_pcs_priv *priv;
+       struct udevice *pcs_dev;
+       phy_interface_t mode;
+       const char *managed;
+       int pcs_phandle;
+       bool neg_mode;
+       int speed;
+       int ret;
+
+       /* PCS property is mandatory */
+       if (!ofnode_read_bool(node, "pcs"))
+               return 0;
+
+       ret = ofnode_read_u32(node, "pcs", &pcs_phandle);
+       if (ret)
+               return ret;
+
+       ret = uclass_get_device_by_phandle_id(UCLASS_MISC, pcs_phandle, 
&pcs_dev);
+       if (ret || !pcs_dev)
+               return ret;
+
+       priv = dev_get_priv(pcs_dev);
+
+       mode = ofnode_read_phy_mode(node);
+       managed = ofnode_read_string(node, "managed");
+       neg_mode = !strncmp(managed, "in-band-status", 
sizeof("in-band-status"));
+
+       airoha_pcs_pre_config(priv, mode);
+
+       ret = airoha_pcs_post_config(priv, mode);
+       if (ret)
+               return ret;
+
+       ret = airoha_pcs_config(priv, neg_mode, mode, NULL, true);
+       if (ret)
+               return ret;
+
+       /* Hardcode speed for linkup */
+       switch (mode) {
+       case PHY_INTERFACE_MODE_USXGMII:
+       case PHY_INTERFACE_MODE_10GBASER:
+               speed = SPEED_10000;
+               break;
+       case PHY_INTERFACE_MODE_2500BASEX:
+               speed = SPEED_2500;
+               break;
+       case PHY_INTERFACE_MODE_SGMII:
+       case PHY_INTERFACE_MODE_1000BASEX:
+               speed = SPEED_1000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       airoha_pcs_link_up(priv, neg_mode, mode, speed, DUPLEX_FULL);
+
+       return 0;
+}
+
 static int airoha_hw_init(struct udevice *dev,
                          struct airoha_eth *eth)
 {
+       ofnode node;
        int ret, i;
 
        /* disable xsi */
@@ -665,6 +730,10 @@ static int airoha_hw_init(struct udevice *dev,
        if (ret)
                return ret;
 
+       ret = reset_deassert_bulk(&eth->xsi_rsts);
+       if (ret)
+               return ret;
+
        mdelay(20);
 
        ret = airoha_fe_init(eth);
@@ -677,6 +746,26 @@ static int airoha_hw_init(struct udevice *dev,
                        return ret;
        }
 
+       ofnode_for_each_subnode(node, dev_ofnode(dev)) {
+               u32 id;
+
+               if (!ofnode_device_is_compatible(node, "airoha,eth-mac"))
+                       continue;
+
+               if (!ofnode_is_enabled(node))
+                       continue;
+
+               ret = ofnode_read_u32(node, "reg", &id);
+               if (ret)
+                       continue;
+
+               /* Skip PCS init for embedded Switch */
+               if (id == 1)
+                       continue;
+
+               airoha_pcs_init(dev, node);
+       }
+
        return 0;
 }
 
-- 
2.50.0

Reply via email to