From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 15889A04A6; Wed, 9 Feb 2022 11:36:09 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2622E411B8; Wed, 9 Feb 2022 11:35:52 +0100 (CET) Received: from smtpbg506.qq.com (smtpbg506.qq.com [203.205.250.33]) by mails.dpdk.org (Postfix) with ESMTP id 0BD8641182 for ; Wed, 9 Feb 2022 11:35:48 +0100 (CET) X-QQ-mid: bizesmtp37t1644402945tb64gmx2 Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by bizesmtp.qq.com (ESMTP) with id ; Wed, 09 Feb 2022 18:35:44 +0800 (CST) X-QQ-SSF: 01400000002000F0L000B00A0000000 X-QQ-FEAT: 1vYwxPNStGmf9bON1C5sDZ6EjmgnuYPWATcbVHq7QmpSkCKh/IFuxd8ldOhHW piotFq77SOm+xlACOsiVNaCQGdY+FWrAA9wyPtETGtr9uI7I5uExmQ3w/WzCBFaUGyvX/5A oZ0nznvQ6rltEtDAz4wKIAyg09F02whaiXytdb1+1u3fGys6DNBKSyM//f4DCsCdgMPxe2h cITiDp6sP1P8ZkNuvgu73tUSpJMyFaInaecd4Puv3vMk+uiTXC+oOoZFhDK+LIdD00JMQXs Q2MoAZh4a+UYefg28TQ74Y1N1KFSKYlCv1VuK4Ap/d3sczAzUhFhWYVOEswJLe8cFiDwwkc P1KkhZhEfnv3k8CecJXDXuvlhVWre+I8J+vIY7D6SV1KQmgvIc= X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Subject: [PATCH v2 06/12] net/ngbe: add support to custom PHY interfaces Date: Wed, 9 Feb 2022 18:42:07 +0800 Message-Id: <20220209104213.602728-7-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220209104213.602728-1-jiawenwu@trustnetic.com> References: <20220209104213.602728-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign1 X-QQ-Bgrelay: 1 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Support sub_device ID 61/62/64 for YT8521S SFP, and 51/52 for M88E1512 PHY. Signed-off-by: Jiawen Wu --- doc/guides/rel_notes/release_22_03.rst | 7 + 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 | 8 ++ drivers/net/ngbe/ngbe_ethdev.c | 6 +- 11 files changed, 314 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..233c34a2d0 100644 --- a/doc/guides/rel_notes/release_22_03.rst +++ b/doc/guides/rel_notes/release_22_03.rst @@ -69,6 +69,13 @@ 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. + - M88E1512 PHY connects to RJ45 + - M88E1512 PHY connects to RGMII combo + - YT8521S PHY connects to SFP + * **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..67e4b4a6fd 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) { /* 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; } /** 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..cb8d65ff27 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -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; diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index cc530fdced..9f42c26f9b 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) { /* 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); } -- 2.21.0.windows.1