Support sub_device ID 61/62/64 for YT8521S SFP, and 51/52 for M88E1512
PHY.

Signed-off-by: Jiawen Wu <jiawe...@trustnetic.com>
---
 doc/guides/rel_notes/release_22_03.rst |   4 +
 drivers/net/ngbe/base/ngbe_devids.h    |  12 +-
 drivers/net/ngbe/base/ngbe_hw.c        |  50 +++++--
 drivers/net/ngbe/base/ngbe_phy.c       |  27 ++--
 drivers/net/ngbe/base/ngbe_phy.h       |   2 +-
 drivers/net/ngbe/base/ngbe_phy_mvl.c   |  55 +++++++-
 drivers/net/ngbe/base/ngbe_phy_mvl.h   |   5 +
 drivers/net/ngbe/base/ngbe_phy_yt.c    | 182 +++++++++++++++++++++----
 drivers/net/ngbe/base/ngbe_phy_yt.h    |  19 ++-
 drivers/net/ngbe/base/ngbe_type.h      |   7 +
 drivers/net/ngbe/ngbe_ethdev.c         |   6 +-
 11 files changed, 310 insertions(+), 59 deletions(-)

diff --git a/doc/guides/rel_notes/release_22_03.rst 
b/doc/guides/rel_notes/release_22_03.rst
index 746f50e84f..3b2517f4c3 100644
--- a/doc/guides/rel_notes/release_22_03.rst
+++ b/doc/guides/rel_notes/release_22_03.rst
@@ -69,6 +69,10 @@ New Features
   * Added AES-XCBC support in lookaside protocol (IPsec) for CN9K & CN10K.
   * Added AES-CMAC support in CN9K & CN10K.
 
+* **Updated Wangxun ngbe driver.**
+
+  * Added support for devices of custom PHY interfaces.
+
 * **Added an API to retrieve event port id of ethdev Rx adapter.**
 
   The new API ``rte_event_eth_rx_adapter_event_port_get()`` was added.
diff --git a/drivers/net/ngbe/base/ngbe_devids.h 
b/drivers/net/ngbe/base/ngbe_devids.h
index 6010cc050e..83eedf423e 100644
--- a/drivers/net/ngbe/base/ngbe_devids.h
+++ b/drivers/net/ngbe/base/ngbe_devids.h
@@ -19,9 +19,11 @@
 #define   NGBE_SUB_DEV_ID_EM_VF                        0x0110
 #define NGBE_DEV_ID_EM                         0x0100
 #define   NGBE_SUB_DEV_ID_EM_MVL_RGMII         0x0200
+#define   NGBE_SUB_DEV_ID_EM_MVL_MIX           0x0252
 #define   NGBE_SUB_DEV_ID_EM_MVL_SFP           0x0403
 #define   NGBE_SUB_DEV_ID_EM_RTL_SGMII         0x0410
 #define   NGBE_SUB_DEV_ID_EM_YT8521S_SFP       0x0460
+#define   NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP   0x0461
 
 #define NGBE_DEV_ID_EM_WX1860AL_W              0x0100
 #define NGBE_DEV_ID_EM_WX1860AL_W_VF           0x0110
@@ -67,15 +69,19 @@
 #define   NGBE_SUB_DEV_ID_EM_SF400_LY_YT       0x0470
 
 /* Assign excessive id with masks */
-#define NGBE_INTERNAL_MASK                     0x000F
-#define NGBE_OEM_MASK                          0x00F0
+#define NGBE_OEM_MASK                          0x00FF
 #define NGBE_WOL_SUP_MASK                      0x4000
 #define NGBE_NCSI_SUP_MASK                     0x8000
 
-#define NGBE_INTERNAL_SFP                      0x0003
+#define NGBE_M88E1512_SFP                      0x0003
 #define NGBE_OCP_CARD                          0x0040
 #define NGBE_LY_M88E1512_SFP                   0x0050
+#define NGBE_M88E1512_RJ45                     0x0051
+#define NGBE_M88E1512_MIX                      0x0052
 #define NGBE_YT8521S_SFP                       0x0060
+#define NGBE_INTERNAL_YT8521S_SFP              0x0061
+#define NGBE_YT8521S_SFP_GPIO                  0x0062
+#define NGBE_INTERNAL_YT8521S_SFP_GPIO         0x0064
 #define NGBE_LY_YT8521S_SFP                    0x0070
 #define NGBE_WOL_SUP                           0x4000
 #define NGBE_NCSI_SUP                          0x8000
diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c
index 72d475ccf9..0eab3f59e1 100644
--- a/drivers/net/ngbe/base/ngbe_hw.c
+++ b/drivers/net/ngbe/base/ngbe_hw.c
@@ -124,8 +124,7 @@ ngbe_reset_misc_em(struct ngbe_hw *hw)
 
        wr32m(hw, NGBE_GPIE, NGBE_GPIE_MSIX, NGBE_GPIE_MSIX);
 
-       if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP ||
-               (hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) {
+       if (hw->gpio_ctl == 1) {
                /* gpio0 is used to power on/off control*/
                wr32(hw, NGBE_GPIODIR, NGBE_GPIODIR_DDR(1));
                wr32(hw, NGBE_GPIODATA, NGBE_GPIOBIT_0);
@@ -1617,19 +1616,21 @@ s32 ngbe_get_link_capabilities_em(struct ngbe_hw *hw,
                                      bool *autoneg)
 {
        s32 status = 0;
-
+       u16 value = 0;
        DEBUGFUNC("\n");
 
        hw->mac.autoneg = *autoneg;
 
-       switch (hw->sub_device_id) {
-       case NGBE_SUB_DEV_ID_EM_RTL_SGMII:
+       if (hw->phy.type == ngbe_phy_rtl) {
                *speed = NGBE_LINK_SPEED_1GB_FULL |
                        NGBE_LINK_SPEED_100M_FULL |
                        NGBE_LINK_SPEED_10M_FULL;
-               break;
-       default:
-               break;
+       }
+
+       if (hw->phy.type == ngbe_phy_yt8521s_sfi) {
+               ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
+               if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1))
+                       *speed = NGBE_LINK_SPEED_1GB_FULL;
        }
 
        return status;
@@ -1815,11 +1816,23 @@ s32 ngbe_set_mac_type(struct ngbe_hw *hw)
        case NGBE_SUB_DEV_ID_EM_MVL_RGMII:
                hw->phy.media_type = ngbe_media_type_copper;
                hw->mac.type = ngbe_mac_em;
+               hw->mac.link_type = ngbe_link_copper;
+               break;
+       case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP:
+               hw->phy.media_type = ngbe_media_type_copper;
+               hw->mac.type = ngbe_mac_em;
+               hw->mac.link_type = ngbe_link_fiber;
                break;
        case NGBE_SUB_DEV_ID_EM_MVL_SFP:
        case NGBE_SUB_DEV_ID_EM_YT8521S_SFP:
                hw->phy.media_type = ngbe_media_type_fiber;
                hw->mac.type = ngbe_mac_em;
+               hw->mac.link_type = ngbe_link_fiber;
+               break;
+       case NGBE_SUB_DEV_ID_EM_MVL_MIX:
+               hw->phy.media_type = ngbe_media_type_unknown;
+               hw->mac.type = ngbe_mac_em;
+               hw->mac.link_type = ngbe_media_type_unknown;
                break;
        case NGBE_SUB_DEV_ID_EM_VF:
                hw->phy.media_type = ngbe_media_type_virtual;
@@ -1871,7 +1884,7 @@ s32 ngbe_enable_rx_dma(struct ngbe_hw *hw, u32 regval)
 void ngbe_map_device_id(struct ngbe_hw *hw)
 {
        u16 oem = hw->sub_system_id & NGBE_OEM_MASK;
-       u16 internal = hw->sub_system_id & NGBE_INTERNAL_MASK;
+
        hw->is_pf = true;
 
        /* move subsystem_device_id to device_id */
@@ -1905,20 +1918,31 @@ void ngbe_map_device_id(struct ngbe_hw *hw)
        case NGBE_DEV_ID_EM_WX1860A1:
        case NGBE_DEV_ID_EM_WX1860A1L:
                hw->device_id = NGBE_DEV_ID_EM;
-               if (oem == NGBE_LY_M88E1512_SFP ||
-                               internal == NGBE_INTERNAL_SFP)
+               if (oem == NGBE_M88E1512_SFP || oem == NGBE_LY_M88E1512_SFP)
                        hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_SFP;
-               else if (hw->sub_system_id == NGBE_SUB_DEV_ID_EM_M88E1512_RJ45)
+               else if (oem == NGBE_M88E1512_RJ45 ||
+                       (hw->sub_system_id == NGBE_SUB_DEV_ID_EM_M88E1512_RJ45))
                        hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_RGMII;
+               else if (oem == NGBE_M88E1512_MIX)
+                       hw->sub_device_id = NGBE_SUB_DEV_ID_EM_MVL_MIX;
                else if (oem == NGBE_YT8521S_SFP ||
-                               oem == NGBE_LY_YT8521S_SFP)
+                        oem == NGBE_YT8521S_SFP_GPIO ||
+                        oem == NGBE_LY_YT8521S_SFP)
                        hw->sub_device_id = NGBE_SUB_DEV_ID_EM_YT8521S_SFP;
+               else if (oem == NGBE_INTERNAL_YT8521S_SFP ||
+                        oem == NGBE_INTERNAL_YT8521S_SFP_GPIO)
+                       hw->sub_device_id = NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP;
                else
                        hw->sub_device_id = NGBE_SUB_DEV_ID_EM_RTL_SGMII;
                break;
        default:
                break;
        }
+
+       if (oem == NGBE_LY_M88E1512_SFP || oem == NGBE_YT8521S_SFP_GPIO ||
+                       oem == NGBE_INTERNAL_YT8521S_SFP_GPIO ||
+                       oem == NGBE_LY_YT8521S_SFP)
+               hw->gpio_ctl = true;
 }
 
 /**
diff --git a/drivers/net/ngbe/base/ngbe_phy.c b/drivers/net/ngbe/base/ngbe_phy.c
index 51b0a2ec60..93450b2977 100644
--- a/drivers/net/ngbe/base/ngbe_phy.c
+++ b/drivers/net/ngbe/base/ngbe_phy.c
@@ -54,8 +54,7 @@ static bool ngbe_probe_phy(struct ngbe_hw *hw, u16 phy_addr)
        if (ngbe_get_phy_id(hw))
                return false;
 
-       hw->phy.type = ngbe_get_phy_type_from_id(hw);
-       if (hw->phy.type == ngbe_phy_unknown)
+       if (ngbe_get_phy_type_from_id(hw))
                return false;
 
        return true;
@@ -174,37 +173,39 @@ s32 ngbe_get_phy_id(struct ngbe_hw *hw)
 
 /**
  *  ngbe_get_phy_type_from_id - Get the phy type
- *  @phy_id: PHY ID information
  *
  **/
-enum ngbe_phy_type ngbe_get_phy_type_from_id(struct ngbe_hw *hw)
+s32 ngbe_get_phy_type_from_id(struct ngbe_hw *hw)
 {
-       enum ngbe_phy_type phy_type;
+       s32 status = 0;
 
        DEBUGFUNC("ngbe_get_phy_type_from_id");
 
        switch (hw->phy.id) {
        case NGBE_PHYID_RTL:
-               phy_type = ngbe_phy_rtl;
+               hw->phy.type = ngbe_phy_rtl;
                break;
        case NGBE_PHYID_MVL:
                if (hw->phy.media_type == ngbe_media_type_fiber)
-                       phy_type = ngbe_phy_mvl_sfi;
+                       hw->phy.type = ngbe_phy_mvl_sfi;
+               else if (hw->phy.media_type == ngbe_media_type_copper)
+                       hw->phy.type = ngbe_phy_mvl;
                else
-                       phy_type = ngbe_phy_mvl;
+                       status = ngbe_check_phy_mode_mvl(hw);
                break;
        case NGBE_PHYID_YT:
                if (hw->phy.media_type == ngbe_media_type_fiber)
-                       phy_type = ngbe_phy_yt8521s_sfi;
+                       hw->phy.type = ngbe_phy_yt8521s_sfi;
                else
-                       phy_type = ngbe_phy_yt8521s;
+                       hw->phy.type = ngbe_phy_yt8521s;
                break;
        default:
-               phy_type = ngbe_phy_unknown;
+               hw->phy.type = ngbe_phy_unknown;
+               status = NGBE_ERR_DEVICE_NOT_SUPPORTED;
                break;
        }
 
-       return phy_type;
+       return status;
 }
 
 /**
@@ -400,11 +401,13 @@ s32 ngbe_init_phy(struct ngbe_hw *hw)
 
        switch (hw->sub_device_id) {
        case NGBE_SUB_DEV_ID_EM_RTL_SGMII:
+       case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP:
                hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl;
                hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl;
                break;
        case NGBE_SUB_DEV_ID_EM_MVL_RGMII:
        case NGBE_SUB_DEV_ID_EM_MVL_SFP:
+       case NGBE_SUB_DEV_ID_EM_MVL_MIX:
                hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl;
                hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl;
                break;
diff --git a/drivers/net/ngbe/base/ngbe_phy.h b/drivers/net/ngbe/base/ngbe_phy.h
index f262ff3350..e93d6a4c4a 100644
--- a/drivers/net/ngbe/base/ngbe_phy.h
+++ b/drivers/net/ngbe/base/ngbe_phy.h
@@ -48,7 +48,7 @@ typedef struct mdi_reg mdi_reg_t;
 s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22);
 
 bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr);
-enum ngbe_phy_type ngbe_get_phy_type_from_id(struct ngbe_hw *hw);
+s32 ngbe_get_phy_type_from_id(struct ngbe_hw *hw);
 s32 ngbe_get_phy_id(struct ngbe_hw *hw);
 s32 ngbe_identify_phy(struct ngbe_hw *hw);
 s32 ngbe_reset_phy(struct ngbe_hw *hw);
diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.c 
b/drivers/net/ngbe/base/ngbe_phy_mvl.c
index 2eb351d258..8a4df90a42 100644
--- a/drivers/net/ngbe/base/ngbe_phy_mvl.c
+++ b/drivers/net/ngbe/base/ngbe_phy_mvl.c
@@ -48,6 +48,31 @@ s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw,
        return 0;
 }
 
+s32 ngbe_check_phy_mode_mvl(struct ngbe_hw *hw)
+{
+       u16 value = 0;
+
+       /* select page 18 reg 20 */
+       ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 18);
+       ngbe_read_phy_reg_mdi(hw, MVL_GEN_CTL, 0, &value);
+       if (MVL_GEN_CTL_MODE(value) == MVL_GEN_CTL_MODE_COPPER) {
+               /* mode select to RGMII-to-copper */
+               hw->phy.type = ngbe_phy_mvl;
+               hw->phy.media_type = ngbe_media_type_copper;
+               hw->mac.link_type = ngbe_link_copper;
+       } else if (MVL_GEN_CTL_MODE(value) == MVL_GEN_CTL_MODE_FIBER) {
+               /* mode select to RGMII-to-sfi */
+               hw->phy.type = ngbe_phy_mvl_sfi;
+               hw->phy.media_type = ngbe_media_type_fiber;
+               hw->mac.link_type = ngbe_link_fiber;
+       } else {
+               DEBUGOUT("marvell 88E1512 mode %x is not supported.\n", value);
+               return NGBE_ERR_DEVICE_NOT_SUPPORTED;
+       }
+
+       return 0;
+}
+
 s32 ngbe_init_phy_mvl(struct ngbe_hw *hw)
 {
        s32 ret_val = 0;
@@ -125,6 +150,29 @@ s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed,
        hw->phy.autoneg_advertised = 0;
 
        if (hw->phy.type == ngbe_phy_mvl) {
+               if (!hw->mac.autoneg) {
+                       switch (speed) {
+                       case NGBE_LINK_SPEED_1GB_FULL:
+                               value = MVL_CTRL_SPEED_SELECT1;
+                               break;
+                       case NGBE_LINK_SPEED_100M_FULL:
+                               value = MVL_CTRL_SPEED_SELECT0;
+                               break;
+                       case NGBE_LINK_SPEED_10M_FULL:
+                               value = 0;
+                               break;
+                       default:
+                               value = MVL_CTRL_SPEED_SELECT0 |
+                                       MVL_CTRL_SPEED_SELECT1;
+                               DEBUGOUT("unknown speed = 0x%x.\n", speed);
+                               break;
+                       }
+                       /* duplex full */
+                       value |= MVL_CTRL_DUPLEX | MVL_CTRL_RESET;
+                       ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
+
+                       goto skip_an;
+               }
                if (speed & NGBE_LINK_SPEED_1GB_FULL) {
                        value_r9 |= MVL_PHY_1000BASET_FULL;
                        hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
@@ -162,7 +210,12 @@ s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed,
                hw->phy.write_reg(hw, MVL_ANA, 0, value);
        }
 
-       value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE;
+       value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE | MVL_CTRL_RESET;
+       ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
+
+skip_an:
+       ngbe_read_phy_reg_mdi(hw, MVL_CTRL, 0, &value);
+       value |= MVL_CTRL_PWDN;
        ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value);
 
        hw->phy.read_reg(hw, MVL_INTR, 0, &value);
diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.h 
b/drivers/net/ngbe/base/ngbe_phy_mvl.h
index a2b5202d4b..8aee236390 100644
--- a/drivers/net/ngbe/base/ngbe_phy_mvl.h
+++ b/drivers/net/ngbe/base/ngbe_phy_mvl.h
@@ -12,8 +12,12 @@
 /* Page 0 for Copper, Page 1 for Fiber */
 #define MVL_CTRL                       0x0
 #define   MVL_CTRL_RESET               MS16(15, 0x1)
+#define          MVL_CTRL_SPEED_SELECT0        MS16(13, 0x1)
 #define   MVL_CTRL_ANE                 MS16(12, 0x1)
+#define   MVL_CTRL_PWDN                        MS16(11, 0x1)
 #define   MVL_CTRL_RESTART_AN          MS16(9, 0x1)
+#define   MVL_CTRL_DUPLEX              MS16(8, 0x1)
+#define          MVL_CTRL_SPEED_SELECT1        MS16(6, 0x1)
 #define MVL_ANA                                0x4
 /* copper */
 #define   MVL_CANA_ASM_PAUSE           MS16(11, 0x1)
@@ -86,6 +90,7 @@ s32 ngbe_read_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, 
u32 device_type,
                        u16 *phy_data);
 s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
                        u16 phy_data);
+s32 ngbe_check_phy_mode_mvl(struct ngbe_hw *hw);
 s32 ngbe_init_phy_mvl(struct ngbe_hw *hw);
 
 s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw);
diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c 
b/drivers/net/ngbe/base/ngbe_phy_yt.c
index 8db0f9ce48..2d184a1c30 100644
--- a/drivers/net/ngbe/base/ngbe_phy_yt.c
+++ b/drivers/net/ngbe/base/ngbe_phy_yt.c
@@ -104,23 +104,22 @@ s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
 
        DEBUGFUNC("ngbe_init_phy_yt");
 
-       if (hw->phy.type != ngbe_phy_yt8521s_sfi)
-               return 0;
-
-       /* select sds area register */
+       /* close sds area register */
        ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
        /* enable interrupts */
-       ngbe_write_phy_reg_mdi(hw, YT_INTR, 0, YT_INTR_ENA_MASK);
-
-       /* select fiber_to_rgmii first in multiplex */
-       ngbe_read_phy_reg_ext_yt(hw, YT_MISC, 0, &value);
-       value |= YT_MISC_FIBER_PRIO;
-       ngbe_write_phy_reg_ext_yt(hw, YT_MISC, 0, value);
+       ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
+                               YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
 
+       /* power down in fiber mode */
        hw->phy.read_reg(hw, YT_BCR, 0, &value);
        value |= YT_BCR_PWDN;
        hw->phy.write_reg(hw, YT_BCR, 0, value);
 
+       /* power down in UTP mode */
+       ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
+       value |= YT_BCR_PWDN;
+       ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+
        return 0;
 }
 
@@ -136,15 +135,44 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
 
        hw->phy.autoneg_advertised = 0;
 
-       if (hw->phy.type == ngbe_phy_yt8521s) {
+       /* check chip_mode first */
+       ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
+       if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(0)) {
+               /* UTP to rgmii */
+               if (!hw->mac.autoneg) {
+                       switch (speed) {
+                       case NGBE_LINK_SPEED_1GB_FULL:
+                               value = YT_BCR_SPEED_SELECT1;
+                               break;
+                       case NGBE_LINK_SPEED_100M_FULL:
+                               value = YT_BCR_SPEED_SELECT0;
+                               break;
+                       case NGBE_LINK_SPEED_10M_FULL:
+                               value = 0;
+                               break;
+                       default:
+                               value = YT_BCR_SPEED_SELECT0 |
+                                       YT_BCR_SPEED_SELECT1;
+                               DEBUGOUT("unknown speed = 0x%x.\n",
+                                       speed);
+                               break;
+                       }
+                       /* duplex full */
+                       value |= YT_BCR_DUPLEX | YT_BCR_RESET;
+                       hw->phy.write_reg(hw, YT_BCR, 0, value);
+
+                       goto skip_an;
+               }
+
                /*disable 100/10base-T Self-negotiation ability*/
                hw->phy.read_reg(hw, YT_ANA, 0, &value);
-               value &= ~(YT_ANA_100BASET_FULL | YT_ANA_10BASET_FULL);
+               value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
+                       YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
                hw->phy.write_reg(hw, YT_ANA, 0, value);
 
                /*disable 1000base-T Self-negotiation ability*/
                hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
-               value &= ~YT_MS_1000BASET_FULL;
+               value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
                hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
 
                if (speed & NGBE_LINK_SPEED_1GB_FULL) {
@@ -172,9 +200,15 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
 
                /* software reset to make the above configuration take effect*/
                hw->phy.read_reg(hw, YT_BCR, 0, &value);
-               value |= YT_BCR_RESET;
+               value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
                hw->phy.write_reg(hw, YT_BCR, 0, value);
-       } else {
+skip_an:
+               /* power on in UTP mode */
+               ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
+               value &= ~YT_BCR_PWDN;
+               ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+       } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1)) {
+               /* fiber to rgmii */
                hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
 
                /* RGMII_Config1 : Config rx and tx training delay */
@@ -190,6 +224,88 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
                /* software reset */
                ngbe_write_phy_reg_sds_ext_yt(hw, 0x0, 0, 0x9140);
 
+               /* power on phy */
+               hw->phy.read_reg(hw, YT_BCR, 0, &value);
+               value &= ~YT_BCR_PWDN;
+               hw->phy.write_reg(hw, YT_BCR, 0, value);
+       } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(2)) {
+               /* power on in UTP mode */
+               ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
+               value &= ~YT_BCR_PWDN;
+               ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+               /* power down in fiber mode */
+               hw->phy.read_reg(hw, YT_BCR, 0, &value);
+               value &= ~YT_BCR_PWDN;
+               hw->phy.write_reg(hw, YT_BCR, 0, value);
+
+               hw->phy.read_reg(hw, YT_SPST, 0, &value);
+               if (value & YT_SPST_LINK) {
+                       /* fiber up */
+                       hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
+               } else {
+                       /* utp up */
+                       /*disable 100/10base-T Self-negotiation ability*/
+                       hw->phy.read_reg(hw, YT_ANA, 0, &value);
+                       value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
+                               YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
+                       hw->phy.write_reg(hw, YT_ANA, 0, value);
+
+                       /*disable 1000base-T Self-negotiation ability*/
+                       hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
+                       value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
+                       hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
+
+                       if (speed & NGBE_LINK_SPEED_1GB_FULL) {
+                               hw->phy.autoneg_advertised |=
+                                               NGBE_LINK_SPEED_1GB_FULL;
+                               value_r9 |= YT_MS_1000BASET_FULL;
+                       }
+                       if (speed & NGBE_LINK_SPEED_100M_FULL) {
+                               hw->phy.autoneg_advertised |=
+                                               NGBE_LINK_SPEED_100M_FULL;
+                               value_r4 |= YT_ANA_100BASET_FULL;
+                       }
+                       if (speed & NGBE_LINK_SPEED_10M_FULL) {
+                               hw->phy.autoneg_advertised |=
+                                               NGBE_LINK_SPEED_10M_FULL;
+                               value_r4 |= YT_ANA_10BASET_FULL;
+                       }
+
+                       /* enable 1000base-T Self-negotiation ability */
+                       hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
+                       value |= value_r9;
+                       hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
+
+                       /* enable 100/10base-T Self-negotiation ability */
+                       hw->phy.read_reg(hw, YT_ANA, 0, &value);
+                       value |= value_r4;
+                       hw->phy.write_reg(hw, YT_ANA, 0, value);
+
+                       /* software reset to make the above configuration
+                        * take effect
+                        */
+                       hw->phy.read_reg(hw, YT_BCR, 0, &value);
+                       value |= YT_BCR_RESET;
+                       hw->phy.write_reg(hw, YT_BCR, 0, value);
+               }
+       } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(4)) {
+               hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
+
+               ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, &value);
+               value |= YT_RGMII_CONF1_MODE;
+               ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
+
+               ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, &value);
+               value &= ~(YT_RGMII_CONF2_SPEED_MASK | YT_RGMII_CONF2_DUPLEX |
+                       YT_RGMII_CONF2_LINKUP);
+               value |= YT_RGMII_CONF2_SPEED(2) | YT_RGMII_CONF2_DUPLEX |
+                       YT_RGMII_CONF2_LINKUP;
+               ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, value);
+
+               ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
+               value &= ~YT_SMI_PHY_SW_RST;
+               ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
+
                /* power on phy */
                hw->phy.read_reg(hw, YT_BCR, 0, &value);
                value &= ~YT_BCR_PWDN;
@@ -214,16 +330,34 @@ s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
                hw->phy.type != ngbe_phy_yt8521s_sfi)
                return NGBE_ERR_PHY_TYPE;
 
-       status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
-       /* sds software reset */
-       ctrl |= YT_BCR_RESET;
-       status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
-
-       for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
+       /* check chip_mode first */
+       ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &ctrl);
+       if (ctrl & YT_CHIP_MODE_MASK) {
+               /* fiber to rgmii */
                status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
-               if (!(ctrl & YT_BCR_RESET))
-                       break;
-               msleep(1);
+               /* sds software reset */
+               ctrl |= YT_BCR_RESET;
+               status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
+
+               for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
+                       status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
+                       if (!(ctrl & YT_BCR_RESET))
+                               break;
+                       msleep(1);
+               }
+       } else {
+               /* UTP to rgmii */
+               status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
+               /* sds software reset */
+               ctrl |= YT_BCR_RESET;
+               status = ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, ctrl);
+
+               for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
+                       status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
+                       if (!(ctrl & YT_BCR_RESET))
+                               break;
+                       msleep(1);
+               }
        }
 
        if (i == YT_PHY_RST_WAIT_PERIOD) {
diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.h 
b/drivers/net/ngbe/base/ngbe_phy_yt.h
index e729e0c854..c8763a90df 100644
--- a/drivers/net/ngbe/base/ngbe_phy_yt.h
+++ b/drivers/net/ngbe/base/ngbe_phy_yt.h
@@ -11,26 +11,41 @@
 
 /* Common EXT */
 #define YT_SMI_PHY                     0xA000
+#define   YT_SMI_PHY_SW_RST            MS16(15, 0x1)
 #define   YT_SMI_PHY_SDS               MS16(1, 0x1) /* 0 for UTP */
 #define YT_CHIP                                0xA001
 #define   YT_CHIP_SW_RST               MS16(15, 0x1)
 #define   YT_CHIP_SW_LDO_EN            MS16(6, 0x1)
+#define   YT_CHIP_MODE_MASK            MS16(0, 0x7)
 #define   YT_CHIP_MODE_SEL(v)          LS16(v, 0, 0x7)
 #define YT_RGMII_CONF1                 0xA003
+#define   YT_RGMII_CONF1_MODE          MS16(15, 0x1)
 #define   YT_RGMII_CONF1_RXDELAY       MS16(10, 0xF)
 #define   YT_RGMII_CONF1_TXDELAY_FE    MS16(4, 0xF)
 #define   YT_RGMII_CONF1_TXDELAY       MS16(0, 0x1)
+#define YT_RGMII_CONF2                 0xA004
+#define   YT_RGMII_CONF2_SPEED_MASK    MS16(6, 0x3)
+#define   YT_RGMII_CONF2_SPEED(v)      LS16(v, 6, 0x3)
+#define   YT_RGMII_CONF2_DUPLEX                MS16(5, 0x1)
+#define   YT_RGMII_CONF2_LINKUP                MS16(4, 0x1)
 #define YT_MISC                                0xA006
 #define   YT_MISC_FIBER_PRIO           MS16(8, 0x1) /* 0 for UTP */
 
 /* MII common registers in UTP and SDS */
 #define YT_BCR                         0x0
 #define   YT_BCR_RESET                 MS16(15, 0x1)
+#define          YT_BCR_SPEED_SELECT0          MS16(13, 0x1)
+#define   YT_BCR_ANE                   MS16(12, 0x1)
 #define   YT_BCR_PWDN                  MS16(11, 0x1)
+#define   YT_BCR_RESTART_AN            MS16(9, 0x1)
+#define   YT_BCR_DUPLEX                        MS16(8, 0x1)
+#define   YT_BCR_SPEED_SELECT1         MS16(6, 0x1)
 #define YT_ANA                         0x4
 /* copper */
 #define   YT_ANA_100BASET_FULL         MS16(8, 0x1)
+#define   YT_ANA_100BASET_HALF         MS16(7, 0x1)
 #define   YT_ANA_10BASET_FULL          MS16(6, 0x1)
+#define   YT_ANA_10BASET_HALF          MS16(5, 0x1)
 /* fiber */
 #define   YT_FANA_PAUSE_MASK           MS16(7, 0x3)
 
@@ -41,6 +56,7 @@
 
 #define YT_MS_CTRL                     0x9
 #define   YT_MS_1000BASET_FULL         MS16(9, 0x1)
+#define   YT_MS_1000BASET_HALF         MS16(8, 0x1)
 #define YT_SPST                                0x11
 #define   YT_SPST_SPEED_MASK           MS16(14, 0x3)
 #define            YT_SPST_SPEED_1000M         LS16(2, 14, 0x3)
@@ -50,7 +66,8 @@
 
 /* UTP only */
 #define YT_INTR                                0x12
-#define   YT_INTR_ENA_MASK             MS16(2, 0x3)
+#define   YT_INTR_ENA_MASK             MS16(10, 0x3)
+#define   YT_SDS_INTR_ENA_MASK         MS16(2, 0x3)
 #define YT_INTR_STATUS                 0x13
 
 s32 ngbe_read_phy_reg_yt(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
diff --git a/drivers/net/ngbe/base/ngbe_type.h 
b/drivers/net/ngbe/base/ngbe_type.h
index 4c995e7397..372e1e72e6 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -44,6 +44,11 @@ enum ngbe_eeprom_type {
        ngbe_eeprom_none /* No NVM support */
 };
 
+enum ngbe_link_type {
+       ngbe_link_fiber = 0,
+       ngbe_link_copper
+};
+
 enum ngbe_mac_type {
        ngbe_mac_unknown = 0,
        ngbe_mac_em,
@@ -312,6 +317,7 @@ struct ngbe_mac_info {
        s32 (*check_overtemp)(struct ngbe_hw *hw);
 
        enum ngbe_mac_type type;
+       enum ngbe_link_type link_type;
        u8 addr[ETH_ADDR_LEN];
        u8 perm_addr[ETH_ADDR_LEN];
 #define NGBE_MAX_MTA                   128
@@ -422,6 +428,7 @@ struct ngbe_hw {
        u32 q_tx_regs[8 * 4];
        bool offset_loaded;
        bool is_pf;
+       bool gpio_ctl;
        struct {
                u64 rx_qp_packets;
                u64 tx_qp_packets;
diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c
index cc530fdced..fdf3aad4fa 100644
--- a/drivers/net/ngbe/ngbe_ethdev.c
+++ b/drivers/net/ngbe/ngbe_ethdev.c
@@ -1097,8 +1097,7 @@ ngbe_dev_start(struct rte_eth_dev *dev)
        /* resume enabled intr since HW reset */
        ngbe_enable_intr(dev);
 
-       if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP ||
-               (hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) {
+       if (hw->gpio_ctl == 1) {
                /* gpio0 is used to power on/off control*/
                wr32(hw, NGBE_GPIODATA, 0);
        }
@@ -1141,8 +1140,7 @@ ngbe_dev_stop(struct rte_eth_dev *dev)
 
        rte_eal_alarm_cancel(ngbe_dev_setup_link_alarm_handler, dev);
 
-       if ((hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_M88E1512_SFP ||
-               (hw->sub_system_id & NGBE_OEM_MASK) == NGBE_LY_YT8521S_SFP) {
+       if (hw->gpio_ctl == 1) {
                /* gpio0 is used to power on/off control*/
                wr32(hw, NGBE_GPIODATA, NGBE_GPIOBIT_0);
        }
-- 
2.21.0.windows.1



Reply via email to