Identify PHY to get the PHY type, and perform a PHY reset.
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
'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 = []
{
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;
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_ */
*/
#include "ngbe_type.h"
+#include "ngbe_phy.h"
#include "ngbe_eeprom.h"
#include "ngbe_mng.h"
#include "ngbe_hw.h"
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);
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;
{
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");
/* 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;
/* 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;
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_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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;
+}
+
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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;
+}
+
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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;
+}
+
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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;
+}
+
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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_ */
/* 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;
};
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 {