[v5,10/24] net/ngbe: identify PHY and reset PHY

Message ID 20210602094108.1575640-11-jiawenwu@trustnetic.com (mailing list archive)
State Changes Requested, archived
Delegated to: Andrew Rybchenko
Headers
Series net: ngbe PMD |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Jiawen Wu June 2, 2021, 9:40 a.m. UTC
  Identify PHY to get the PHY type, and perform a PHY reset.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ngbe/base/meson.build    |   4 +
 drivers/net/ngbe/base/ngbe_dummy.h   |  40 +++
 drivers/net/ngbe/base/ngbe_hw.c      |  38 +++
 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 |  44 +++
 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  |  66 +++++
 drivers/net/ngbe/base/ngbe_type.h    |  17 ++
 13 files changed, 1073 insertions(+)
 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
  

Patch

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..ebd163d9e6 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"
@@ -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..d1b4cc9e5f
--- /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 claus22 */
+	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 -TERR_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(&reg, &reg22);
+
+	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(&reg, &reg22);
+
+	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..9c98a8ecaf
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_phy_rtl.c
@@ -0,0 +1,44 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.
+ */
+
+#include "ngbe_phy_rtl.h"
+
+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(&reg, &reg22);
+
+	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(&reg, &reg22);
+
+	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)
+{
+	UNREFERENCED_PARAMETER(hw);
+	return 0;
+}
+
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(&reg, &reg22);
+
+	/* 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(&reg, &reg22);
+
+	/* 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..03b53ece86
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_phy_yt.h
@@ -0,0 +1,66 @@ 
+/* 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_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 21756c4690..b5c05e0f2f 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -93,6 +93,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;
@@ -102,8 +103,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 {