]> git.droids-corp.org - dpdk.git/commitdiff
net/ngbe: support custom PHY interfaces
authorJiawen Wu <jiawenwu@trustnetic.com>
Wed, 9 Feb 2022 10:42:07 +0000 (18:42 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 11 Feb 2022 12:49:12 +0000 (13:49 +0100)
Support sub_device ID 61/62/64 for YT8521S SFP, and 51/52 for M88E1512
PHY.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
doc/guides/rel_notes/release_22_03.rst
drivers/net/ngbe/base/ngbe_devids.h
drivers/net/ngbe/base/ngbe_hw.c
drivers/net/ngbe/base/ngbe_phy.c
drivers/net/ngbe/base/ngbe_phy.h
drivers/net/ngbe/base/ngbe_phy_mvl.c
drivers/net/ngbe/base/ngbe_phy_mvl.h
drivers/net/ngbe/base/ngbe_phy_yt.c
drivers/net/ngbe/base/ngbe_phy_yt.h
drivers/net/ngbe/base/ngbe_type.h
drivers/net/ngbe/ngbe_ethdev.c

index db516c04ed314e26ef57085846542066c0b8bdc2..5e0254e4a08fdf4e87a6feff7ee77e1d5093fe87 100644 (file)
@@ -103,6 +103,13 @@ New Features
   * Added rte_flow support for matching GENEVE packets.
   * Added rte_flow support for matching eCPRI packets.
 
+* **Updated Wangxun ngbe driver.**
+
+  * Added support for devices of custom PHY interfaces.
+    - M88E1512 PHY connects to RJ45
+    - M88E1512 PHY connects to RGMII combo
+    - YT8521S PHY connects to SFP
+
 * **Updated Marvell cnxk crypto PMD.**
 
   * Added SHA256-HMAC support in lookaside protocol (IPsec) for CN10K.
index 6010cc050e8408f8ddea1572095c30ba951a98ba..83eedf423ef4db798cfafdb897c6e7f24d4efb66 100644 (file)
 #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
 #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
index 72d475ccf9e98c701bca93f1d251c626e444a3f9..67e4b4a6fdbac9fbe3eaf4a6224f130978155855 100644 (file)
@@ -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) {
                /* 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_link_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;
 }
 
 /**
index 51b0a2ec604a3c04081a44093bd6f8b8e50e4198..93450b2977acb8a9697a9256296fe4ff1fba6230 100644 (file)
@@ -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;
index f262ff3350d84b83c87af33b69fa3cded70bf6f2..e93d6a4c4a0f4316ba158691b583a23ef44492e3 100644 (file)
@@ -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);
index 2eb351d2582315b22f5235b66cef106f9a762ca1..8a4df90a42676825d7de39bc52b43e53a44ffca3 100644 (file)
@@ -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);
index a2b5202d4b93c9cae312a620d7a6a0a2a2ff93d9..8aee236390ca7a853b48d32fc0f364a6ae51ff86 100644 (file)
 /* 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);
index 8db0f9ce48e9f5e0b50882d517b805fd4b00b533..2d184a1c30d325d072edab46769d7150a1e27f7d 100644 (file)
@@ -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) {
index e729e0c8542cdddb537e435bac7905313672d858..c8763a90df788df01cc54e027eb3979b4bef5b28 100644 (file)
 
 /* 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,
index 4c995e7397aea1cc89a03d3e7c708e4e24d42eed..cb8d65ff274ec743b07ad53256413b615d776a1a 100644 (file)
@@ -44,6 +44,12 @@ enum ngbe_eeprom_type {
        ngbe_eeprom_none /* No NVM support */
 };
 
+enum ngbe_link_type {
+       ngbe_link_type_unknown = 0,
+       ngbe_link_fiber,
+       ngbe_link_copper
+};
+
 enum ngbe_mac_type {
        ngbe_mac_unknown = 0,
        ngbe_mac_em,
@@ -312,6 +318,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 +429,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;
index cc530fdced8fc42174c836d25a672b430284d213..9f42c26f9b16e4f90b8f5f05a96d146b6174fdec 100644 (file)
@@ -1097,8 +1097,7 @@ skip_link_setup:
        /* 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) {
                /* 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) {
                /* gpio0 is used to power on/off control*/
                wr32(hw, NGBE_GPIODATA, NGBE_GPIOBIT_0);
        }