From patchwork Thu Jun 17 10:59:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 94333 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id D2CC3A0C4D; Thu, 17 Jun 2021 12:59:10 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0A09A41139; Thu, 17 Jun 2021 12:58:27 +0200 (CEST) Received: from smtpbgau2.qq.com (smtpbgau2.qq.com [54.206.34.216]) by mails.dpdk.org (Postfix) with ESMTP id 7C3DD41136 for ; Thu, 17 Jun 2021 12:58:24 +0200 (CEST) X-QQ-mid: bizesmtp46t1623927499tmuhuiac Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Thu, 17 Jun 2021 18:58:18 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: PAtBXkQ2bGBlEDPZc3Oho6FtHxw9Jf9jSfOfG/rYoVvsBYNjbuqFm5hjA56xb zNengHWTu+FwMy66NotKvZ8WKVjr/x/0B98N8oA1ST+fqtkXrkrEBrB3QTvX7Pw3y4wSZ++ DK+tZUU/Ol1Dfnks7BQaoQqRZfH3Qpledzb58vONszzChnGdgA7L1pjXB9Jd7laUu/zSAdN K3wHMRXsRb3LFtnfAn3yGQNHcLIsnK4tUxEKHVi6dnbDN4BmWxX1ij9MprTtQ3gb/mwCnpa lUu/vBtF6ogu9DzctZ/28nMxXQWDeNzALx9+eAU8+dJ8Oh5WpZEAEpODQ1Bh/UX/fXgtRz8 JH2VHerHI1MMUlJvOOrfRN1VOmobw== X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Thu, 17 Jun 2021 18:59:54 +0800 Message-Id: <20210617110005.4132926-9-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210617110005.4132926-1-jiawenwu@trustnetic.com> References: <20210617110005.4132926-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign5 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v6 08/19] net/ngbe: identify PHY and reset PHY 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 Sender: "dev" Identify PHY to get the PHY type, and perform a PHY reset. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/base/meson.build | 4 + drivers/net/ngbe/base/ngbe_dummy.h | 40 +++ drivers/net/ngbe/base/ngbe_hw.c | 40 ++- drivers/net/ngbe/base/ngbe_hw.h | 2 + drivers/net/ngbe/base/ngbe_phy.c | 426 +++++++++++++++++++++++++++ drivers/net/ngbe/base/ngbe_phy.h | 60 ++++ drivers/net/ngbe/base/ngbe_phy_mvl.c | 89 ++++++ drivers/net/ngbe/base/ngbe_phy_mvl.h | 92 ++++++ drivers/net/ngbe/base/ngbe_phy_rtl.c | 65 ++++ drivers/net/ngbe/base/ngbe_phy_rtl.h | 83 ++++++ drivers/net/ngbe/base/ngbe_phy_yt.c | 112 +++++++ drivers/net/ngbe/base/ngbe_phy_yt.h | 67 +++++ drivers/net/ngbe/base/ngbe_type.h | 17 ++ 13 files changed, 1096 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ngbe/base/ngbe_phy.c create mode 100644 drivers/net/ngbe/base/ngbe_phy.h create mode 100644 drivers/net/ngbe/base/ngbe_phy_mvl.c create mode 100644 drivers/net/ngbe/base/ngbe_phy_mvl.h create mode 100644 drivers/net/ngbe/base/ngbe_phy_rtl.c create mode 100644 drivers/net/ngbe/base/ngbe_phy_rtl.h create mode 100644 drivers/net/ngbe/base/ngbe_phy_yt.c create mode 100644 drivers/net/ngbe/base/ngbe_phy_yt.h diff --git a/drivers/net/ngbe/base/meson.build b/drivers/net/ngbe/base/meson.build index ddd122ec45..146134f671 100644 --- a/drivers/net/ngbe/base/meson.build +++ b/drivers/net/ngbe/base/meson.build @@ -5,6 +5,10 @@ sources = [ 'ngbe_eeprom.c', 'ngbe_hw.c', 'ngbe_mng.c', + 'ngbe_phy.c', + 'ngbe_phy_rtl.c', + 'ngbe_phy_mvl.c', + 'ngbe_phy_yt.c', ] error_cflags = [] diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h index d0081acc2b..15017cfd82 100644 --- a/drivers/net/ngbe/base/ngbe_dummy.h +++ b/drivers/net/ngbe/base/ngbe_dummy.h @@ -64,6 +64,39 @@ static inline s32 ngbe_mac_init_thermal_ssth_dummy(struct ngbe_hw *TUP0) { return NGBE_ERR_OPS_DUMMY; } +static inline s32 ngbe_mac_check_overtemp_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +/* struct ngbe_phy_operations */ +static inline s32 ngbe_phy_identify_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_reset_hw_dummy(struct ngbe_hw *TUP0) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_read_reg_dummy(struct ngbe_hw *TUP0, u32 TUP1, + u32 TUP2, u16 *TUP3) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_write_reg_dummy(struct ngbe_hw *TUP0, u32 TUP1, + u32 TUP2, u16 TUP3) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_read_reg_unlocked_dummy(struct ngbe_hw *TUP0, + u32 TUP1, u32 TUP2, u16 *TUP3) +{ + return NGBE_ERR_OPS_DUMMY; +} +static inline s32 ngbe_phy_write_reg_unlocked_dummy(struct ngbe_hw *TUP0, + u32 TUP1, u32 TUP2, u16 TUP3) +{ + return NGBE_ERR_OPS_DUMMY; +} static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) { hw->bus.set_lan_id = ngbe_bus_set_lan_id_dummy; @@ -75,6 +108,13 @@ static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw) hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy; hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy; hw->mac.init_thermal_sensor_thresh = ngbe_mac_init_thermal_ssth_dummy; + hw->mac.check_overtemp = ngbe_mac_check_overtemp_dummy; + hw->phy.identify = ngbe_phy_identify_dummy; + hw->phy.reset_hw = ngbe_phy_reset_hw_dummy; + hw->phy.read_reg = ngbe_phy_read_reg_dummy; + hw->phy.write_reg = ngbe_phy_write_reg_dummy; + hw->phy.read_reg_unlocked = ngbe_phy_read_reg_unlocked_dummy; + hw->phy.write_reg_unlocked = ngbe_phy_write_reg_unlocked_dummy; } #endif /* _NGBE_TYPE_DUMMY_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c index 9fa40f7de1..5723213209 100644 --- a/drivers/net/ngbe/base/ngbe_hw.c +++ b/drivers/net/ngbe/base/ngbe_hw.c @@ -4,6 +4,7 @@ */ #include "ngbe_type.h" +#include "ngbe_phy.h" #include "ngbe_eeprom.h" #include "ngbe_mng.h" #include "ngbe_hw.h" @@ -94,7 +95,7 @@ ngbe_reset_misc_em(struct ngbe_hw *hw) hw->mac.init_thermal_sensor_thresh(hw); - /* enable mac transmiter */ + /* enable mac transmitter */ wr32m(hw, NGBE_MACTXCFG, NGBE_MACTXCFG_TE, NGBE_MACTXCFG_TE); /* sellect GMII */ @@ -124,6 +125,15 @@ s32 ngbe_reset_hw_em(struct ngbe_hw *hw) if (status != 0) return status; + /* Identify PHY and related function pointers */ + status = ngbe_init_phy(hw); + if (status) + return status; + + /* Reset PHY */ + if (!hw->phy.reset_disable) + hw->phy.reset_hw(hw); + wr32(hw, NGBE_RST, NGBE_RST_LAN(hw->bus.lan_id)); ngbe_flush(hw); msec_delay(50); @@ -307,6 +317,24 @@ s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw) return 0; } +s32 ngbe_mac_check_overtemp(struct ngbe_hw *hw) +{ + s32 status = 0; + u32 ts_state; + + DEBUGFUNC("ngbe_mac_check_overtemp"); + + /* Check that the LASI temp alarm status was triggered */ + ts_state = rd32(hw, NGBE_TSALM); + + if (ts_state & NGBE_TSALM_HI) + status = NGBE_ERR_UNDERTEMP; + else if (ts_state & NGBE_TSALM_LO) + status = NGBE_ERR_OVERTEMP; + + return status; +} + void ngbe_disable_rx(struct ngbe_hw *hw) { u32 pfdtxgswc; @@ -434,6 +462,7 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) { struct ngbe_bus_info *bus = &hw->bus; struct ngbe_mac_info *mac = &hw->mac; + struct ngbe_phy_info *phy = &hw->phy; struct ngbe_rom_info *rom = &hw->rom; DEBUGFUNC("ngbe_init_ops_pf"); @@ -441,6 +470,14 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) /* BUS */ bus->set_lan_id = ngbe_set_lan_id_multi_port; + /* PHY */ + phy->identify = ngbe_identify_phy; + phy->read_reg = ngbe_read_phy_reg; + phy->write_reg = ngbe_write_phy_reg; + phy->read_reg_unlocked = ngbe_read_phy_reg_mdi; + phy->write_reg_unlocked = ngbe_write_phy_reg_mdi; + phy->reset_hw = ngbe_reset_phy; + /* MAC */ mac->init_hw = ngbe_init_hw; mac->reset_hw = ngbe_reset_hw_em; @@ -450,6 +487,7 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw) /* Manageability interface */ mac->init_thermal_sensor_thresh = ngbe_init_thermal_sensor_thresh; + mac->check_overtemp = ngbe_mac_check_overtemp; /* EEPROM */ rom->init_params = ngbe_init_eeprom_params; diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h index 39b2fe696b..3c8e646bb7 100644 --- a/drivers/net/ngbe/base/ngbe_hw.h +++ b/drivers/net/ngbe/base/ngbe_hw.h @@ -21,10 +21,12 @@ s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask); void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask); s32 ngbe_init_thermal_sensor_thresh(struct ngbe_hw *hw); +s32 ngbe_mac_check_overtemp(struct ngbe_hw *hw); void ngbe_disable_rx(struct ngbe_hw *hw); s32 ngbe_init_shared_code(struct ngbe_hw *hw); s32 ngbe_set_mac_type(struct ngbe_hw *hw); s32 ngbe_init_ops_pf(struct ngbe_hw *hw); +s32 ngbe_init_phy(struct ngbe_hw *hw); void ngbe_map_device_id(struct ngbe_hw *hw); #endif /* _NGBE_HW_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy.c b/drivers/net/ngbe/base/ngbe_phy.c new file mode 100644 index 0000000000..0467e1e66e --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy.c @@ -0,0 +1,426 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#include "ngbe_hw.h" +#include "ngbe_phy.h" + +s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22) +{ + bool match = 1; + switch (reg->device_type) { + case NGBE_MD_DEV_PMA_PMD: + switch (reg->addr) { + case NGBE_MD_PHY_ID_HIGH: + case NGBE_MD_PHY_ID_LOW: + reg22->page = 0; + reg22->addr = reg->addr; + reg22->device_type = 0; + break; + default: + match = 0; + } + break; + default: + match = 0; + break; + } + + if (!match) { + reg22->page = reg->device_type; + reg22->device_type = reg->device_type; + reg22->addr = reg->addr; + } + + return 0; +} + +/** + * ngbe_probe_phy - Identify a single address for a PHY + * @hw: pointer to hardware structure + * @phy_addr: PHY address to probe + * + * Returns true if PHY found + */ +static bool ngbe_probe_phy(struct ngbe_hw *hw, u16 phy_addr) +{ + if (!ngbe_validate_phy_addr(hw, phy_addr)) { + DEBUGOUT("Unable to validate PHY address 0x%04X\n", + phy_addr); + return false; + } + + 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) + return false; + + return true; +} + +/** + * ngbe_identify_phy - Get physical layer module + * @hw: pointer to hardware structure + * + * Determines the physical layer module found on the current adapter. + **/ +s32 ngbe_identify_phy(struct ngbe_hw *hw) +{ + s32 err = NGBE_ERR_PHY_ADDR_INVALID; + u16 phy_addr; + + DEBUGFUNC("ngbe_identify_phy"); + + if (hw->phy.type != ngbe_phy_unknown) + return 0; + + /* select clause22 */ + wr32(hw, NGBE_MDIOMODE, NGBE_MDIOMODE_MASK); + + for (phy_addr = 0; phy_addr < NGBE_MAX_PHY_ADDR; phy_addr++) { + if (ngbe_probe_phy(hw, phy_addr)) { + err = 0; + break; + } + } + + return err; +} + +/** + * ngbe_check_reset_blocked - check status of MNG FW veto bit + * @hw: pointer to the hardware structure + * + * This function checks the STAT.MNGVETO bit to see if there are + * any constraints on link from manageability. For MAC's that don't + * have this bit just return faluse since the link can not be blocked + * via this method. + **/ +s32 ngbe_check_reset_blocked(struct ngbe_hw *hw) +{ + u32 mmngc; + + DEBUGFUNC("ngbe_check_reset_blocked"); + + mmngc = rd32(hw, NGBE_STAT); + if (mmngc & NGBE_STAT_MNGVETO) { + DEBUGOUT("MNG_VETO bit detected.\n"); + return true; + } + + return false; +} + +/** + * ngbe_validate_phy_addr - Determines phy address is valid + * @hw: pointer to hardware structure + * @phy_addr: PHY address + * + **/ +bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr) +{ + u16 phy_id = 0; + bool valid = false; + + DEBUGFUNC("ngbe_validate_phy_addr"); + + if (hw->sub_device_id == NGBE_SUB_DEV_ID_EM_YT8521S_SFP) + return true; + + hw->phy.addr = phy_addr; + hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH, + NGBE_MD_DEV_PMA_PMD, &phy_id); + + if (phy_id != 0xFFFF && phy_id != 0x0) + valid = true; + + DEBUGOUT("PHY ID HIGH is 0x%04X\n", phy_id); + + return valid; +} + +/** + * ngbe_get_phy_id - Get the phy ID + * @hw: pointer to hardware structure + * + **/ +s32 ngbe_get_phy_id(struct ngbe_hw *hw) +{ + u32 err; + u16 phy_id_high = 0; + u16 phy_id_low = 0; + + DEBUGFUNC("ngbe_get_phy_id"); + + err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH, + NGBE_MD_DEV_PMA_PMD, + &phy_id_high); + hw->phy.id = (u32)(phy_id_high << 16); + + err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW, + NGBE_MD_DEV_PMA_PMD, + &phy_id_low); + hw->phy.id |= (u32)(phy_id_low & NGBE_PHY_REVISION_MASK); + hw->phy.revision = (u32)(phy_id_low & ~NGBE_PHY_REVISION_MASK); + + DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X\n", + phy_id_high, phy_id_low); + + return err; +} + +/** + * 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) +{ + enum ngbe_phy_type phy_type; + + DEBUGFUNC("ngbe_get_phy_type_from_id"); + + switch (hw->phy.id) { + case NGBE_PHYID_RTL: + 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; + else + phy_type = ngbe_phy_mvl; + break; + case NGBE_PHYID_YT: + if (hw->phy.media_type == ngbe_media_type_fiber) + phy_type = ngbe_phy_yt8521s_sfi; + else + phy_type = ngbe_phy_yt8521s; + break; + default: + phy_type = ngbe_phy_unknown; + break; + } + + return phy_type; +} + +/** + * ngbe_reset_phy - Performs a PHY reset + * @hw: pointer to hardware structure + **/ +s32 ngbe_reset_phy(struct ngbe_hw *hw) +{ + s32 err = 0; + + DEBUGFUNC("ngbe_reset_phy"); + + if (hw->phy.type == ngbe_phy_unknown) + err = ngbe_identify_phy(hw); + + if (err != 0 || hw->phy.type == ngbe_phy_none) + return err; + + /* Don't reset PHY if it's shut down due to overtemp. */ + if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP) + return err; + + /* Blocked by MNG FW so bail */ + if (ngbe_check_reset_blocked(hw)) + return err; + + switch (hw->phy.type) { + case ngbe_phy_rtl: + err = ngbe_reset_phy_rtl(hw); + break; + case ngbe_phy_mvl: + case ngbe_phy_mvl_sfi: + err = ngbe_reset_phy_mvl(hw); + break; + case ngbe_phy_yt8521s: + case ngbe_phy_yt8521s_sfi: + err = ngbe_reset_phy_yt(hw); + break; + default: + break; + } + + return err; +} + +/** + * ngbe_read_phy_mdi - Reads a value from a specified PHY register without + * the SWFW lock + * @hw: pointer to hardware structure + * @reg_addr: 32 bit address of PHY register to read + * @device_type: 5 bit device type + * @phy_data: Pointer to read data from PHY register + **/ +s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 *phy_data) +{ + u32 command, data; + + /* Setup and write the address cycle command */ + command = NGBE_MDIOSCA_REG(reg_addr) | + NGBE_MDIOSCA_DEV(device_type) | + NGBE_MDIOSCA_PORT(hw->phy.addr); + wr32(hw, NGBE_MDIOSCA, command); + + command = NGBE_MDIOSCD_CMD_READ | + NGBE_MDIOSCD_BUSY | + NGBE_MDIOSCD_CLOCK(6); + wr32(hw, NGBE_MDIOSCD, command); + + /* + * Check every 10 usec to see if the address cycle completed. + * The MDI Command bit will clear when the operation is + * complete + */ + if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, + 0, NULL, 100, 100)) { + DEBUGOUT("PHY address command did not complete\n"); + return NGBE_ERR_PHY; + } + + data = rd32(hw, NGBE_MDIOSCD); + *phy_data = (u16)NGBE_MDIOSCD_DAT_R(data); + + return 0; +} + +/** + * ngbe_read_phy_reg - Reads a value from a specified PHY register + * using the SWFW lock - this function is needed in most cases + * @hw: pointer to hardware structure + * @reg_addr: 32 bit address of PHY register to read + * @device_type: 5 bit device type + * @phy_data: Pointer to read data from PHY register + **/ +s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data) +{ + s32 err; + u32 gssr = hw->phy.phy_semaphore_mask; + + DEBUGFUNC("ngbe_read_phy_reg"); + + if (hw->mac.acquire_swfw_sync(hw, gssr)) + return NGBE_ERR_SWFW_SYNC; + + err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type, + phy_data); + + hw->mac.release_swfw_sync(hw, gssr); + + return err; +} + +/** + * ngbe_write_phy_reg_mdi - Writes a value to specified PHY register + * without SWFW lock + * @hw: pointer to hardware structure + * @reg_addr: 32 bit PHY register to write + * @device_type: 5 bit device type + * @phy_data: Data to write to the PHY register + **/ +s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data) +{ + u32 command; + + /* write command */ + command = NGBE_MDIOSCA_REG(reg_addr) | + NGBE_MDIOSCA_DEV(device_type) | + NGBE_MDIOSCA_PORT(hw->phy.addr); + wr32(hw, NGBE_MDIOSCA, command); + + command = NGBE_MDIOSCD_CMD_WRITE | + NGBE_MDIOSCD_DAT(phy_data) | + NGBE_MDIOSCD_BUSY | + NGBE_MDIOSCD_CLOCK(6); + wr32(hw, NGBE_MDIOSCD, command); + + /* wait for completion */ + if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, + 0, NULL, 100, 100)) { + TLOG_DEBUG("PHY write cmd didn't complete\n"); + return NGBE_ERR_PHY; + } + + return 0; +} + +/** + * ngbe_write_phy_reg - Writes a value to specified PHY register + * using SWFW lock- this function is needed in most cases + * @hw: pointer to hardware structure + * @reg_addr: 32 bit PHY register to write + * @device_type: 5 bit device type + * @phy_data: Data to write to the PHY register + **/ +s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data) +{ + s32 err; + u32 gssr = hw->phy.phy_semaphore_mask; + + DEBUGFUNC("ngbe_write_phy_reg"); + + if (hw->mac.acquire_swfw_sync(hw, gssr)) + err = NGBE_ERR_SWFW_SYNC; + + err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type, + phy_data); + + hw->mac.release_swfw_sync(hw, gssr); + + return err; +} + +/** + * ngbe_init_phy - PHY specific init + * @hw: pointer to hardware structure + * + * Initialize any function pointers that were not able to be + * set during init_shared_code because the PHY type was + * not known. + * + **/ +s32 ngbe_init_phy(struct ngbe_hw *hw) +{ + struct ngbe_phy_info *phy = &hw->phy; + s32 err = 0; + + DEBUGFUNC("ngbe_init_phy"); + + hw->phy.addr = 0; + + switch (hw->sub_device_id) { + case NGBE_SUB_DEV_ID_EM_RTL_SGMII: + 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: + hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl; + hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl; + break; + case NGBE_SUB_DEV_ID_EM_YT8521S_SFP: + hw->phy.read_reg_unlocked = ngbe_read_phy_reg_yt; + hw->phy.write_reg_unlocked = ngbe_write_phy_reg_yt; + break; + default: + break; + } + + hw->phy.phy_semaphore_mask = NGBE_MNGSEM_SWPHY; + + /* Identify the PHY */ + err = phy->identify(hw); + + return err; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy.h b/drivers/net/ngbe/base/ngbe_phy.h new file mode 100644 index 0000000000..59d9efe025 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation + */ + +#ifndef _NGBE_PHY_H_ +#define _NGBE_PHY_H_ + +#include "ngbe_type.h" +#include "ngbe_phy_rtl.h" +#include "ngbe_phy_mvl.h" +#include "ngbe_phy_yt.h" + +/****************************************************************************** + * PHY MDIO Registers: + ******************************************************************************/ +#define NGBE_MAX_PHY_ADDR 32 + +/* (dev_type = 1) */ +#define NGBE_MD_DEV_PMA_PMD 0x1 +#define NGBE_MD_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/ +#define NGBE_MD_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ +#define NGBE_PHY_REVISION_MASK 0xFFFFFFF0 + +/* IEEE 802.3 Clause 22 */ +struct mdi_reg_22 { + u16 page; + u16 addr; + u16 device_type; +}; +typedef struct mdi_reg_22 mdi_reg_22_t; + +/* IEEE 802.3ae Clause 45 */ +struct mdi_reg { + u16 device_type; + u16 addr; +}; +typedef struct mdi_reg mdi_reg_t; + +#define NGBE_MD22_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/ +#define NGBE_MD22_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ + +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_id(struct ngbe_hw *hw); +s32 ngbe_identify_phy(struct ngbe_hw *hw); +s32 ngbe_reset_phy(struct ngbe_hw *hw); +s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 *phy_data); +s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 phy_data); +s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data); +s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data); +s32 ngbe_check_reset_blocked(struct ngbe_hw *hw); + +#endif /* _NGBE_PHY_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.c b/drivers/net/ngbe/base/ngbe_phy_mvl.c new file mode 100644 index 0000000000..40419a61f6 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.c @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy_mvl.h" + +#define MVL_PHY_RST_WAIT_PERIOD 5 + +s32 ngbe_read_phy_reg_mvl(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + + if (hw->phy.media_type == ngbe_media_type_fiber) + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 1); + else + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 0); + + ngbe_mdi_map_register(®, ®22); + + ngbe_read_phy_reg_mdi(hw, reg22.addr, reg22.device_type, phy_data); + + return 0; +} + +s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + + if (hw->phy.media_type == ngbe_media_type_fiber) + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 1); + else + ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 0); + + ngbe_mdi_map_register(®, ®22); + + ngbe_write_phy_reg_mdi(hw, reg22.addr, reg22.device_type, phy_data); + + return 0; +} + +s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw) +{ + u32 i; + u16 ctrl = 0; + s32 status = 0; + + DEBUGFUNC("ngbe_reset_phy_mvl"); + + if (hw->phy.type != ngbe_phy_mvl && hw->phy.type != ngbe_phy_mvl_sfi) + return NGBE_ERR_PHY_TYPE; + + /* select page 18 reg 20 */ + status = ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 18); + + /* mode select to RGMII-to-copper or RGMII-to-sfi*/ + if (hw->phy.type == ngbe_phy_mvl) + ctrl = MVL_GEN_CTL_MODE_COPPER; + else + ctrl = MVL_GEN_CTL_MODE_FIBER; + status = ngbe_write_phy_reg_mdi(hw, MVL_GEN_CTL, 0, ctrl); + /* mode reset */ + ctrl |= MVL_GEN_CTL_RESET; + status = ngbe_write_phy_reg_mdi(hw, MVL_GEN_CTL, 0, ctrl); + + for (i = 0; i < MVL_PHY_RST_WAIT_PERIOD; i++) { + status = ngbe_read_phy_reg_mdi(hw, MVL_GEN_CTL, 0, &ctrl); + if (!(ctrl & MVL_GEN_CTL_RESET)) + break; + msleep(1); + } + + if (i == MVL_PHY_RST_WAIT_PERIOD) { + DEBUGOUT("PHY reset polling failed to complete.\n"); + return NGBE_ERR_RESET_FAILED; + } + + return status; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy_mvl.h b/drivers/net/ngbe/base/ngbe_phy_mvl.h new file mode 100644 index 0000000000..a88ace9ec1 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_mvl.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy.h" + +#ifndef _NGBE_PHY_MVL_H_ +#define _NGBE_PHY_MVL_H_ + +#define NGBE_PHYID_MVL 0x01410DD0U + +/* Page 0 for Copper, Page 1 for Fiber */ +#define MVL_CTRL 0x0 +#define MVL_CTRL_RESET MS16(15, 0x1) +#define MVL_CTRL_ANE MS16(12, 0x1) +#define MVL_CTRL_RESTART_AN MS16(9, 0x1) +#define MVL_ANA 0x4 +/* copper */ +#define MVL_CANA_ASM_PAUSE MS16(11, 0x1) +#define MVL_CANA_PAUSE MS16(10, 0x1) +#define MVL_PHY_100BASET_FULL MS16(8, 0x1) +#define MVL_PHY_100BASET_HALF MS16(7, 0x1) +#define MVL_PHY_10BASET_FULL MS16(6, 0x1) +#define MVL_PHY_10BASET_HALF MS16(5, 0x1) +/* fiber */ +#define MVL_FANA_PAUSE_MASK MS16(7, 0x3) +#define MVL_FANA_SYM_PAUSE LS16(1, 7, 0x3) +#define MVL_FANA_ASM_PAUSE LS16(2, 7, 0x3) +#define MVL_PHY_1000BASEX_HALF MS16(6, 0x1) +#define MVL_PHY_1000BASEX_FULL MS16(5, 0x1) +#define MVL_LPAR 0x5 +#define MVL_CLPAR_ASM_PAUSE MS(11, 0x1) +#define MVL_CLPAR_PAUSE MS(10, 0x1) +#define MVL_FLPAR_PAUSE_MASK MS(7, 0x3) +#define MVL_PHY_1000BASET 0x9 +#define MVL_PHY_1000BASET_FULL MS16(9, 0x1) +#define MVL_PHY_1000BASET_HALF MS16(8, 0x1) +#define MVL_CTRL1 0x10 +#define MVL_CTRL1_INTR_POL MS16(2, 0x1) +#define MVL_PHYSR 0x11 +#define MVL_PHYSR_SPEED_MASK MS16(14, 0x3) +#define MVL_PHYSR_SPEED_1000M LS16(2, 14, 0x3) +#define MVL_PHYSR_SPEED_100M LS16(1, 14, 0x3) +#define MVL_PHYSR_SPEED_10M LS16(0, 14, 0x3) +#define MVL_PHYSR_LINK MS16(10, 0x1) +#define MVL_INTR_EN 0x12 +#define MVL_INTR_EN_ANC MS16(11, 0x1) +#define MVL_INTR_EN_LSC MS16(10, 0x1) +#define MVL_INTR 0x13 +#define MVL_INTR_ANC MS16(11, 0x1) +#define MVL_INTR_LSC MS16(10, 0x1) + +/* Page 2 */ +#define MVL_RGM_CTL2 0x15 +#define MVL_RGM_CTL2_TTC MS16(4, 0x1) +#define MVL_RGM_CTL2_RTC MS16(5, 0x1) +/* Page 3 */ +#define MVL_LEDFCR 0x10 +#define MVL_LEDFCR_CTL1 MS16(4, 0xF) +#define MVL_LEDFCR_CTL1_CONF LS16(6, 4, 0xF) +#define MVL_LEDFCR_CTL0 MS16(0, 0xF) +#define MVL_LEDFCR_CTL0_CONF LS16(1, 0, 0xF) +#define MVL_LEDPCR 0x11 +#define MVL_LEDPCR_CTL1 MS16(2, 0x3) +#define MVL_LEDPCR_CTL1_CONF LS16(1, 2, 0x3) +#define MVL_LEDPCR_CTL0 MS16(0, 0x3) +#define MVL_LEDPCR_CTL0_CONF LS16(1, 0, 0x3) +#define MVL_LEDTCR 0x12 +#define MVL_LEDTCR_INTR_POL MS16(11, 0x1) +#define MVL_LEDTCR_INTR_EN MS16(7, 0x1) +/* Page 18 */ +#define MVL_GEN_CTL 0x14 +#define MVL_GEN_CTL_RESET MS16(15, 0x1) +#define MVL_GEN_CTL_MODE(v) LS16(v, 0, 0x7) +#define MVL_GEN_CTL_MODE_COPPER LS16(0, 0, 0x7) +#define MVL_GEN_CTL_MODE_FIBER LS16(2, 0, 0x7) + +/* reg 22 */ +#define MVL_PAGE_SEL 22 + +/* reg 19_0 INT status*/ +#define MVL_PHY_ANC 0x0800 +#define MVL_PHY_LSC 0x0400 + +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_reset_phy_mvl(struct ngbe_hw *hw); + +#endif /* _NGBE_PHY_MVL_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.c b/drivers/net/ngbe/base/ngbe_phy_rtl.c new file mode 100644 index 0000000000..0703ad9396 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_rtl.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy_rtl.h" + +#define RTL_PHY_RST_WAIT_PERIOD 5 + +s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + ngbe_mdi_map_register(®, ®22); + + wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page); + *phy_data = 0xFFFF & rd32(hw, NGBE_PHY_CONFIG(reg22.addr)); + + return 0; +} + +s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + ngbe_mdi_map_register(®, ®22); + + wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page); + wr32(hw, NGBE_PHY_CONFIG(reg22.addr), phy_data); + + return 0; +} + +s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw) +{ + u16 value = 0, i; + s32 status = 0; + + DEBUGFUNC("ngbe_reset_phy_rtl"); + + value |= RTL_BMCR_RESET; + status = hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value); + + for (i = 0; i < RTL_PHY_RST_WAIT_PERIOD; i++) { + status = hw->phy.read_reg(hw, RTL_BMCR, RTL_DEV_ZERO, &value); + if (!(value & RTL_BMCR_RESET)) + break; + msleep(1); + } + + if (i == RTL_PHY_RST_WAIT_PERIOD) { + DEBUGOUT("PHY reset polling failed to complete.\n"); + return NGBE_ERR_RESET_FAILED; + } + + return status; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy_rtl.h b/drivers/net/ngbe/base/ngbe_phy_rtl.h new file mode 100644 index 0000000000..ecb60b0ddd --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_rtl.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy.h" + +#ifndef _NGBE_PHY_RTL_H_ +#define _NGBE_PHY_RTL_H_ + +#define NGBE_PHYID_RTL 0x001CC800U + +/* Page 0 */ +#define RTL_DEV_ZERO 0 +#define RTL_BMCR 0x0 +#define RTL_BMCR_RESET MS16(15, 0x1) +#define RTL_BMCR_SPEED_SELECT0 MS16(13, 0x1) +#define RTL_BMCR_ANE MS16(12, 0x1) +#define RTL_BMCR_RESTART_AN MS16(9, 0x1) +#define RTL_BMCR_DUPLEX MS16(8, 0x1) +#define RTL_BMCR_SPEED_SELECT1 MS16(6, 0x1) +#define RTL_BMSR 0x1 +#define RTL_BMSR_ANC MS16(5, 0x1) +#define RTL_ID1_OFFSET 0x2 +#define RTL_ID2_OFFSET 0x3 +#define RTL_ID_MASK 0xFFFFFC00U +#define RTL_ANAR 0x4 +#define RTL_ANAR_APAUSE MS16(11, 0x1) +#define RTL_ANAR_PAUSE MS16(10, 0x1) +#define RTL_ANAR_100F MS16(8, 0x1) +#define RTL_ANAR_100H MS16(7, 0x1) +#define RTL_ANAR_10F MS16(6, 0x1) +#define RTL_ANAR_10H MS16(5, 0x1) +#define RTL_ANLPAR 0x5 +#define RTL_ANLPAR_LP MS16(10, 0x3) +#define RTL_GBCR 0x9 +#define RTL_GBCR_1000F MS16(9, 0x1) +/* Page 0xa42*/ +#define RTL_GSR 0x10 +#define RTL_GSR_ST MS16(0, 0x7) +#define RTL_GSR_ST_LANON MS16(0, 0x3) +#define RTL_INER 0x12 +#define RTL_INER_LSC MS16(4, 0x1) +#define RTL_INER_ANC MS16(3, 0x1) +/* Page 0xa43*/ +#define RTL_PHYSR 0x1A +#define RTL_PHYSR_SPEED_MASK MS16(4, 0x3) +#define RTL_PHYSR_SPEED_RES LS16(3, 4, 0x3) +#define RTL_PHYSR_SPEED_1000M LS16(2, 4, 0x3) +#define RTL_PHYSR_SPEED_100M LS16(1, 4, 0x3) +#define RTL_PHYSR_SPEED_10M LS16(0, 4, 0x3) +#define RTL_PHYSR_DP MS16(3, 0x1) +#define RTL_PHYSR_RTLS MS16(2, 0x1) +#define RTL_INSR 0x1D +#define RTL_INSR_ACCESS MS16(5, 0x1) +#define RTL_INSR_LSC MS16(4, 0x1) +#define RTL_INSR_ANC MS16(3, 0x1) +/* Page 0xa46*/ +#define RTL_SCR 0x14 +#define RTL_SCR_EXTINI MS16(1, 0x1) +#define RTL_SCR_EFUSE MS16(0, 0x1) +/* Page 0xa47*/ +/* Page 0xd04*/ +#define RTL_LCR 0x10 +#define RTL_EEELCR 0x11 +#define RTL_LPCR 0x12 + +/* INTERNAL PHY CONTROL */ +#define RTL_PAGE_SELECT 31 +#define NGBE_INTERNAL_PHY_OFFSET_MAX 32 +#define NGBE_INTERNAL_PHY_ID 0x000732 + +#define NGBE_INTPHY_LED0 0x0010 +#define NGBE_INTPHY_LED1 0x0040 +#define NGBE_INTPHY_LED2 0x2000 + +s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 *phy_data); +s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 phy_data); + +s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw); + +#endif /* _NGBE_PHY_RTL_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c new file mode 100644 index 0000000000..84b20de45c --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_yt.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy_yt.h" + +#define YT_PHY_RST_WAIT_PERIOD 5 + +s32 ngbe_read_phy_reg_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + + ngbe_mdi_map_register(®, ®22); + + /* Read MII reg according to media type */ + if (hw->phy.media_type == ngbe_media_type_fiber) { + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, + reg22.device_type, YT_SMI_PHY_SDS); + ngbe_read_phy_reg_mdi(hw, reg22.addr, + reg22.device_type, phy_data); + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, + reg22.device_type, 0); + } else { + ngbe_read_phy_reg_mdi(hw, reg22.addr, + reg22.device_type, phy_data); + } + + return 0; +} + +s32 ngbe_write_phy_reg_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data) +{ + mdi_reg_t reg; + mdi_reg_22_t reg22; + + reg.device_type = device_type; + reg.addr = reg_addr; + + ngbe_mdi_map_register(®, ®22); + + /* Write MII reg according to media type */ + if (hw->phy.media_type == ngbe_media_type_fiber) { + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, + reg22.device_type, YT_SMI_PHY_SDS); + ngbe_write_phy_reg_mdi(hw, reg22.addr, + reg22.device_type, phy_data); + ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, + reg22.device_type, 0); + } else { + ngbe_write_phy_reg_mdi(hw, reg22.addr, + reg22.device_type, phy_data); + } + + return 0; +} + +s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data) +{ + ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr); + ngbe_read_phy_reg_mdi(hw, 0x1F, device_type, phy_data); + + return 0; +} + +s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data) +{ + ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr); + ngbe_write_phy_reg_mdi(hw, 0x1F, device_type, phy_data); + + return 0; +} + +s32 ngbe_reset_phy_yt(struct ngbe_hw *hw) +{ + u32 i; + u16 ctrl = 0; + s32 status = 0; + + DEBUGFUNC("ngbe_reset_phy_yt"); + + if (hw->phy.type != ngbe_phy_yt8521s && + 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++) { + status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl); + if (!(ctrl & YT_BCR_RESET)) + break; + msleep(1); + } + + if (i == YT_PHY_RST_WAIT_PERIOD) { + DEBUGOUT("PHY reset polling failed to complete.\n"); + return NGBE_ERR_RESET_FAILED; + } + + return status; +} + diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.h b/drivers/net/ngbe/base/ngbe_phy_yt.h new file mode 100644 index 0000000000..80fd420a63 --- /dev/null +++ b/drivers/net/ngbe/base/ngbe_phy_yt.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd. + */ + +#include "ngbe_phy.h" + +#ifndef _NGBE_PHY_YT_H_ +#define _NGBE_PHY_YT_H_ + +#define NGBE_PHYID_YT 0x00000110U + +/* Common EXT */ +#define YT_SMI_PHY 0xA000 +#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_SEL(v) LS16(v, 0, 0x7) +#define YT_RGMII_CONF1 0xA003 +#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_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_PWDN MS16(11, 0x1) +#define YT_ANA 0x4 +/* copper */ +#define YT_ANA_100BASET_FULL MS16(8, 0x1) +#define YT_ANA_10BASET_FULL MS16(6, 0x1) +/* fiber */ +#define YT_FANA_PAUSE_MASK MS16(7, 0x3) + +#define YT_LPAR 0x5 +#define YT_CLPAR_ASM_PAUSE MS(11, 0x1) +#define YT_CLPAR_PAUSE MS(10, 0x1) +#define YT_FLPAR_PAUSE_MASK MS(7, 0x3) + +#define YT_MS_CTRL 0x9 +#define YT_MS_1000BASET_FULL MS16(9, 0x1) +#define YT_SPST 0x11 +#define YT_SPST_SPEED_MASK MS16(14, 0x3) +#define YT_SPST_SPEED_1000M LS16(2, 14, 0x3) +#define YT_SPST_SPEED_100M LS16(1, 14, 0x3) +#define YT_SPST_SPEED_10M LS16(0, 14, 0x3) +#define YT_SPST_LINK MS16(10, 0x1) + +/* UTP only */ +#define YT_INTR 0x12 +#define YT_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, + u16 *phy_data); +s32 ngbe_write_phy_reg_yt(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, + u16 phy_data); +s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 *phy_data); +s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw, + u32 reg_addr, u32 device_type, u16 phy_data); + +s32 ngbe_reset_phy_yt(struct ngbe_hw *hw); + +#endif /* _NGBE_PHY_YT_H_ */ diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h index 55c686c0a3..8ed14560c3 100644 --- a/drivers/net/ngbe/base/ngbe_type.h +++ b/drivers/net/ngbe/base/ngbe_type.h @@ -94,6 +94,7 @@ struct ngbe_mac_info { /* Manageability interface */ s32 (*init_thermal_sensor_thresh)(struct ngbe_hw *hw); + s32 (*check_overtemp)(struct ngbe_hw *hw); enum ngbe_mac_type type; u32 max_tx_queues; @@ -103,8 +104,24 @@ struct ngbe_mac_info { }; struct ngbe_phy_info { + s32 (*identify)(struct ngbe_hw *hw); + s32 (*reset_hw)(struct ngbe_hw *hw); + s32 (*read_reg)(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data); + s32 (*write_reg)(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data); + s32 (*read_reg_unlocked)(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data); + s32 (*write_reg_unlocked)(struct ngbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data); + enum ngbe_media_type media_type; enum ngbe_phy_type type; + u32 addr; + u32 id; + u32 revision; + u32 phy_semaphore_mask; + bool reset_disable; }; struct ngbe_hw {