144e97550SJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause
244e97550SJiawen Wu * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
344e97550SJiawen Wu * Copyright(c) 2010-2017 Intel Corporation
444e97550SJiawen Wu */
544e97550SJiawen Wu
644e97550SJiawen Wu #include "ngbe_hw.h"
744e97550SJiawen Wu #include "ngbe_phy.h"
844e97550SJiawen Wu
ngbe_mdi_map_register(mdi_reg_t * reg,mdi_reg_22_t * reg22)944e97550SJiawen Wu s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22)
1044e97550SJiawen Wu {
1144e97550SJiawen Wu bool match = 1;
1244e97550SJiawen Wu switch (reg->device_type) {
1344e97550SJiawen Wu case NGBE_MD_DEV_PMA_PMD:
1444e97550SJiawen Wu switch (reg->addr) {
1544e97550SJiawen Wu case NGBE_MD_PHY_ID_HIGH:
1644e97550SJiawen Wu case NGBE_MD_PHY_ID_LOW:
1744e97550SJiawen Wu reg22->page = 0;
1844e97550SJiawen Wu reg22->addr = reg->addr;
1944e97550SJiawen Wu reg22->device_type = 0;
2044e97550SJiawen Wu break;
2144e97550SJiawen Wu default:
2244e97550SJiawen Wu match = 0;
2344e97550SJiawen Wu }
2444e97550SJiawen Wu break;
2544e97550SJiawen Wu default:
2644e97550SJiawen Wu match = 0;
2744e97550SJiawen Wu break;
2844e97550SJiawen Wu }
2944e97550SJiawen Wu
3044e97550SJiawen Wu if (!match) {
3144e97550SJiawen Wu reg22->page = reg->device_type;
3244e97550SJiawen Wu reg22->device_type = reg->device_type;
3344e97550SJiawen Wu reg22->addr = reg->addr;
3444e97550SJiawen Wu }
3544e97550SJiawen Wu
3644e97550SJiawen Wu return 0;
3744e97550SJiawen Wu }
3844e97550SJiawen Wu
3944e97550SJiawen Wu /**
4044e97550SJiawen Wu * ngbe_probe_phy - Identify a single address for a PHY
4144e97550SJiawen Wu * @hw: pointer to hardware structure
4244e97550SJiawen Wu * @phy_addr: PHY address to probe
4344e97550SJiawen Wu *
4444e97550SJiawen Wu * Returns true if PHY found
4544e97550SJiawen Wu */
ngbe_probe_phy(struct ngbe_hw * hw,u16 phy_addr)4644e97550SJiawen Wu static bool ngbe_probe_phy(struct ngbe_hw *hw, u16 phy_addr)
4744e97550SJiawen Wu {
4844e97550SJiawen Wu if (!ngbe_validate_phy_addr(hw, phy_addr)) {
49c811e6a4SJiawen Wu DEBUGOUT("Unable to validate PHY address 0x%04X",
5044e97550SJiawen Wu phy_addr);
5144e97550SJiawen Wu return false;
5244e97550SJiawen Wu }
5344e97550SJiawen Wu
5444e97550SJiawen Wu if (ngbe_get_phy_id(hw))
5544e97550SJiawen Wu return false;
5644e97550SJiawen Wu
571c44384fSJiawen Wu if (ngbe_get_phy_type_from_id(hw))
5844e97550SJiawen Wu return false;
5944e97550SJiawen Wu
6044e97550SJiawen Wu return true;
6144e97550SJiawen Wu }
6244e97550SJiawen Wu
6344e97550SJiawen Wu /**
6444e97550SJiawen Wu * ngbe_identify_phy - Get physical layer module
6544e97550SJiawen Wu * @hw: pointer to hardware structure
6644e97550SJiawen Wu *
6744e97550SJiawen Wu * Determines the physical layer module found on the current adapter.
6844e97550SJiawen Wu **/
ngbe_identify_phy(struct ngbe_hw * hw)6944e97550SJiawen Wu s32 ngbe_identify_phy(struct ngbe_hw *hw)
7044e97550SJiawen Wu {
7144e97550SJiawen Wu s32 err = NGBE_ERR_PHY_ADDR_INVALID;
7244e97550SJiawen Wu u16 phy_addr;
7344e97550SJiawen Wu
7444e97550SJiawen Wu if (hw->phy.type != ngbe_phy_unknown)
7544e97550SJiawen Wu return 0;
7644e97550SJiawen Wu
7744e97550SJiawen Wu /* select clause22 */
7844e97550SJiawen Wu wr32(hw, NGBE_MDIOMODE, NGBE_MDIOMODE_MASK);
7944e97550SJiawen Wu
8044e97550SJiawen Wu for (phy_addr = 0; phy_addr < NGBE_MAX_PHY_ADDR; phy_addr++) {
8144e97550SJiawen Wu if (ngbe_probe_phy(hw, phy_addr)) {
8244e97550SJiawen Wu err = 0;
8344e97550SJiawen Wu break;
8444e97550SJiawen Wu }
8544e97550SJiawen Wu }
8644e97550SJiawen Wu
8744e97550SJiawen Wu return err;
8844e97550SJiawen Wu }
8944e97550SJiawen Wu
9044e97550SJiawen Wu /**
9144e97550SJiawen Wu * ngbe_check_reset_blocked - check status of MNG FW veto bit
9244e97550SJiawen Wu * @hw: pointer to the hardware structure
9344e97550SJiawen Wu *
9444e97550SJiawen Wu * This function checks the STAT.MNGVETO bit to see if there are
9544e97550SJiawen Wu * any constraints on link from manageability. For MAC's that don't
9644e97550SJiawen Wu * have this bit just return faluse since the link can not be blocked
9744e97550SJiawen Wu * via this method.
9844e97550SJiawen Wu **/
ngbe_check_reset_blocked(struct ngbe_hw * hw)9944e97550SJiawen Wu s32 ngbe_check_reset_blocked(struct ngbe_hw *hw)
10044e97550SJiawen Wu {
10144e97550SJiawen Wu u32 mmngc;
10244e97550SJiawen Wu
10344e97550SJiawen Wu mmngc = rd32(hw, NGBE_STAT);
10444e97550SJiawen Wu if (mmngc & NGBE_STAT_MNGVETO) {
105c811e6a4SJiawen Wu DEBUGOUT("MNG_VETO bit detected.");
10644e97550SJiawen Wu return true;
10744e97550SJiawen Wu }
10844e97550SJiawen Wu
10944e97550SJiawen Wu return false;
11044e97550SJiawen Wu }
11144e97550SJiawen Wu
11244e97550SJiawen Wu /**
11344e97550SJiawen Wu * ngbe_validate_phy_addr - Determines phy address is valid
11444e97550SJiawen Wu * @hw: pointer to hardware structure
11544e97550SJiawen Wu * @phy_addr: PHY address
11644e97550SJiawen Wu *
11744e97550SJiawen Wu **/
ngbe_validate_phy_addr(struct ngbe_hw * hw,u32 phy_addr)11844e97550SJiawen Wu bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr)
11944e97550SJiawen Wu {
12044e97550SJiawen Wu u16 phy_id = 0;
12144e97550SJiawen Wu bool valid = false;
12244e97550SJiawen Wu
12344e97550SJiawen Wu hw->phy.addr = phy_addr;
124abe02c6cSJiawen Wu hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW,
12544e97550SJiawen Wu NGBE_MD_DEV_PMA_PMD, &phy_id);
12644e97550SJiawen Wu
12744e97550SJiawen Wu if (phy_id != 0xFFFF && phy_id != 0x0)
12844e97550SJiawen Wu valid = true;
12944e97550SJiawen Wu
130abe02c6cSJiawen Wu DEBUGOUT("PHY ID LOW is 0x%04X", phy_id);
13144e97550SJiawen Wu
13244e97550SJiawen Wu return valid;
13344e97550SJiawen Wu }
13444e97550SJiawen Wu
13544e97550SJiawen Wu /**
13644e97550SJiawen Wu * ngbe_get_phy_id - Get the phy ID
13744e97550SJiawen Wu * @hw: pointer to hardware structure
13844e97550SJiawen Wu *
13944e97550SJiawen Wu **/
ngbe_get_phy_id(struct ngbe_hw * hw)14044e97550SJiawen Wu s32 ngbe_get_phy_id(struct ngbe_hw *hw)
14144e97550SJiawen Wu {
14244e97550SJiawen Wu u32 err;
14344e97550SJiawen Wu u16 phy_id_high = 0;
14444e97550SJiawen Wu u16 phy_id_low = 0;
14544e97550SJiawen Wu
14644e97550SJiawen Wu err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH,
14744e97550SJiawen Wu NGBE_MD_DEV_PMA_PMD,
14844e97550SJiawen Wu &phy_id_high);
14944e97550SJiawen Wu hw->phy.id = (u32)(phy_id_high << 16);
15044e97550SJiawen Wu
15144e97550SJiawen Wu err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW,
15244e97550SJiawen Wu NGBE_MD_DEV_PMA_PMD,
15344e97550SJiawen Wu &phy_id_low);
15444e97550SJiawen Wu hw->phy.id |= (u32)(phy_id_low & NGBE_PHY_REVISION_MASK);
15544e97550SJiawen Wu hw->phy.revision = (u32)(phy_id_low & ~NGBE_PHY_REVISION_MASK);
15644e97550SJiawen Wu
157c811e6a4SJiawen Wu DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X",
15844e97550SJiawen Wu phy_id_high, phy_id_low);
15944e97550SJiawen Wu
16044e97550SJiawen Wu return err;
16144e97550SJiawen Wu }
16244e97550SJiawen Wu
16344e97550SJiawen Wu /**
16444e97550SJiawen Wu * ngbe_get_phy_type_from_id - Get the phy type
16544e97550SJiawen Wu *
16644e97550SJiawen Wu **/
ngbe_get_phy_type_from_id(struct ngbe_hw * hw)1671c44384fSJiawen Wu s32 ngbe_get_phy_type_from_id(struct ngbe_hw *hw)
16844e97550SJiawen Wu {
1691c44384fSJiawen Wu s32 status = 0;
17044e97550SJiawen Wu
17144e97550SJiawen Wu switch (hw->phy.id) {
17244e97550SJiawen Wu case NGBE_PHYID_RTL:
1731c44384fSJiawen Wu hw->phy.type = ngbe_phy_rtl;
17444e97550SJiawen Wu break;
17544e97550SJiawen Wu case NGBE_PHYID_MVL:
17644e97550SJiawen Wu if (hw->phy.media_type == ngbe_media_type_fiber)
1771c44384fSJiawen Wu hw->phy.type = ngbe_phy_mvl_sfi;
1781c44384fSJiawen Wu else if (hw->phy.media_type == ngbe_media_type_copper)
1791c44384fSJiawen Wu hw->phy.type = ngbe_phy_mvl;
18044e97550SJiawen Wu else
1811c44384fSJiawen Wu status = ngbe_check_phy_mode_mvl(hw);
18244e97550SJiawen Wu break;
1835eade8a3SJiawen Wu case NGBE_PHYID_YT8521:
1845eade8a3SJiawen Wu case NGBE_PHYID_YT8531:
18544e97550SJiawen Wu if (hw->phy.media_type == ngbe_media_type_fiber)
1861c44384fSJiawen Wu hw->phy.type = ngbe_phy_yt8521s_sfi;
18744e97550SJiawen Wu else
1881c44384fSJiawen Wu hw->phy.type = ngbe_phy_yt8521s;
18944e97550SJiawen Wu break;
19044e97550SJiawen Wu default:
1911c44384fSJiawen Wu hw->phy.type = ngbe_phy_unknown;
1921c44384fSJiawen Wu status = NGBE_ERR_DEVICE_NOT_SUPPORTED;
19344e97550SJiawen Wu break;
19444e97550SJiawen Wu }
19544e97550SJiawen Wu
1961c44384fSJiawen Wu return status;
19744e97550SJiawen Wu }
19844e97550SJiawen Wu
19944e97550SJiawen Wu /**
20044e97550SJiawen Wu * ngbe_reset_phy - Performs a PHY reset
20144e97550SJiawen Wu * @hw: pointer to hardware structure
20244e97550SJiawen Wu **/
ngbe_reset_phy(struct ngbe_hw * hw)20344e97550SJiawen Wu s32 ngbe_reset_phy(struct ngbe_hw *hw)
20444e97550SJiawen Wu {
20544e97550SJiawen Wu s32 err = 0;
20644e97550SJiawen Wu
20744e97550SJiawen Wu if (hw->phy.type == ngbe_phy_unknown)
20844e97550SJiawen Wu err = ngbe_identify_phy(hw);
20944e97550SJiawen Wu
21044e97550SJiawen Wu if (err != 0 || hw->phy.type == ngbe_phy_none)
21144e97550SJiawen Wu return err;
21244e97550SJiawen Wu
213*5f1ab0d5SJiawen Wu if (hw->ncsi_enabled)
214*5f1ab0d5SJiawen Wu return err;
215*5f1ab0d5SJiawen Wu
21644e97550SJiawen Wu /* Don't reset PHY if it's shut down due to overtemp. */
21744e97550SJiawen Wu if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP)
21844e97550SJiawen Wu return err;
21944e97550SJiawen Wu
22044e97550SJiawen Wu /* Blocked by MNG FW so bail */
22144e97550SJiawen Wu if (ngbe_check_reset_blocked(hw))
22244e97550SJiawen Wu return err;
22344e97550SJiawen Wu
22444e97550SJiawen Wu switch (hw->phy.type) {
22544e97550SJiawen Wu case ngbe_phy_rtl:
22644e97550SJiawen Wu err = ngbe_reset_phy_rtl(hw);
22744e97550SJiawen Wu break;
22844e97550SJiawen Wu case ngbe_phy_mvl:
22944e97550SJiawen Wu case ngbe_phy_mvl_sfi:
23044e97550SJiawen Wu err = ngbe_reset_phy_mvl(hw);
23144e97550SJiawen Wu break;
23244e97550SJiawen Wu case ngbe_phy_yt8521s:
23344e97550SJiawen Wu case ngbe_phy_yt8521s_sfi:
23444e97550SJiawen Wu err = ngbe_reset_phy_yt(hw);
23544e97550SJiawen Wu break;
23644e97550SJiawen Wu default:
23744e97550SJiawen Wu break;
23844e97550SJiawen Wu }
23944e97550SJiawen Wu
24044e97550SJiawen Wu return err;
24144e97550SJiawen Wu }
24244e97550SJiawen Wu
24344e97550SJiawen Wu /**
24444e97550SJiawen Wu * ngbe_read_phy_mdi - Reads a value from a specified PHY register without
24544e97550SJiawen Wu * the SWFW lock
24644e97550SJiawen Wu * @hw: pointer to hardware structure
24744e97550SJiawen Wu * @reg_addr: 32 bit address of PHY register to read
24844e97550SJiawen Wu * @device_type: 5 bit device type
24944e97550SJiawen Wu * @phy_data: Pointer to read data from PHY register
25044e97550SJiawen Wu **/
ngbe_read_phy_reg_mdi(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)25144e97550SJiawen Wu s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
25244e97550SJiawen Wu u16 *phy_data)
25344e97550SJiawen Wu {
25444e97550SJiawen Wu u32 command, data;
25544e97550SJiawen Wu
25644e97550SJiawen Wu /* Setup and write the address cycle command */
25744e97550SJiawen Wu command = NGBE_MDIOSCA_REG(reg_addr) |
25844e97550SJiawen Wu NGBE_MDIOSCA_DEV(device_type) |
25944e97550SJiawen Wu NGBE_MDIOSCA_PORT(hw->phy.addr);
26044e97550SJiawen Wu wr32(hw, NGBE_MDIOSCA, command);
26144e97550SJiawen Wu
26244e97550SJiawen Wu command = NGBE_MDIOSCD_CMD_READ |
26344e97550SJiawen Wu NGBE_MDIOSCD_BUSY |
26444e97550SJiawen Wu NGBE_MDIOSCD_CLOCK(6);
26544e97550SJiawen Wu wr32(hw, NGBE_MDIOSCD, command);
26644e97550SJiawen Wu
26744e97550SJiawen Wu /*
26844e97550SJiawen Wu * Check every 10 usec to see if the address cycle completed.
26944e97550SJiawen Wu * The MDI Command bit will clear when the operation is
27044e97550SJiawen Wu * complete
27144e97550SJiawen Wu */
27244e97550SJiawen Wu if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY,
27344e97550SJiawen Wu 0, NULL, 100, 100)) {
274c811e6a4SJiawen Wu DEBUGOUT("PHY address command did not complete");
27544e97550SJiawen Wu return NGBE_ERR_PHY;
27644e97550SJiawen Wu }
27744e97550SJiawen Wu
27844e97550SJiawen Wu data = rd32(hw, NGBE_MDIOSCD);
27944e97550SJiawen Wu *phy_data = (u16)NGBE_MDIOSCD_DAT_R(data);
28044e97550SJiawen Wu
28144e97550SJiawen Wu return 0;
28244e97550SJiawen Wu }
28344e97550SJiawen Wu
28444e97550SJiawen Wu /**
28544e97550SJiawen Wu * ngbe_read_phy_reg - Reads a value from a specified PHY register
28644e97550SJiawen Wu * using the SWFW lock - this function is needed in most cases
28744e97550SJiawen Wu * @hw: pointer to hardware structure
28844e97550SJiawen Wu * @reg_addr: 32 bit address of PHY register to read
28944e97550SJiawen Wu * @device_type: 5 bit device type
29044e97550SJiawen Wu * @phy_data: Pointer to read data from PHY register
29144e97550SJiawen Wu **/
ngbe_read_phy_reg(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)29244e97550SJiawen Wu s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
29344e97550SJiawen Wu u32 device_type, u16 *phy_data)
29444e97550SJiawen Wu {
29544e97550SJiawen Wu s32 err;
29644e97550SJiawen Wu
29744e97550SJiawen Wu err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type,
29844e97550SJiawen Wu phy_data);
29944e97550SJiawen Wu
30044e97550SJiawen Wu return err;
30144e97550SJiawen Wu }
30244e97550SJiawen Wu
30344e97550SJiawen Wu /**
30444e97550SJiawen Wu * ngbe_write_phy_reg_mdi - Writes a value to specified PHY register
30544e97550SJiawen Wu * without SWFW lock
30644e97550SJiawen Wu * @hw: pointer to hardware structure
30744e97550SJiawen Wu * @reg_addr: 32 bit PHY register to write
30844e97550SJiawen Wu * @device_type: 5 bit device type
30944e97550SJiawen Wu * @phy_data: Data to write to the PHY register
31044e97550SJiawen Wu **/
ngbe_write_phy_reg_mdi(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)31144e97550SJiawen Wu s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr,
31244e97550SJiawen Wu u32 device_type, u16 phy_data)
31344e97550SJiawen Wu {
31444e97550SJiawen Wu u32 command;
31544e97550SJiawen Wu
31644e97550SJiawen Wu /* write command */
31744e97550SJiawen Wu command = NGBE_MDIOSCA_REG(reg_addr) |
31844e97550SJiawen Wu NGBE_MDIOSCA_DEV(device_type) |
31944e97550SJiawen Wu NGBE_MDIOSCA_PORT(hw->phy.addr);
32044e97550SJiawen Wu wr32(hw, NGBE_MDIOSCA, command);
32144e97550SJiawen Wu
32244e97550SJiawen Wu command = NGBE_MDIOSCD_CMD_WRITE |
32344e97550SJiawen Wu NGBE_MDIOSCD_DAT(phy_data) |
32444e97550SJiawen Wu NGBE_MDIOSCD_BUSY |
32544e97550SJiawen Wu NGBE_MDIOSCD_CLOCK(6);
32644e97550SJiawen Wu wr32(hw, NGBE_MDIOSCD, command);
32744e97550SJiawen Wu
32844e97550SJiawen Wu /* wait for completion */
32944e97550SJiawen Wu if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY,
33044e97550SJiawen Wu 0, NULL, 100, 100)) {
331c811e6a4SJiawen Wu DEBUGOUT("PHY write cmd didn't complete");
33244e97550SJiawen Wu return NGBE_ERR_PHY;
33344e97550SJiawen Wu }
33444e97550SJiawen Wu
33544e97550SJiawen Wu return 0;
33644e97550SJiawen Wu }
33744e97550SJiawen Wu
33844e97550SJiawen Wu /**
33944e97550SJiawen Wu * ngbe_write_phy_reg - Writes a value to specified PHY register
34044e97550SJiawen Wu * using SWFW lock- this function is needed in most cases
34144e97550SJiawen Wu * @hw: pointer to hardware structure
34244e97550SJiawen Wu * @reg_addr: 32 bit PHY register to write
34344e97550SJiawen Wu * @device_type: 5 bit device type
34444e97550SJiawen Wu * @phy_data: Data to write to the PHY register
34544e97550SJiawen Wu **/
ngbe_write_phy_reg(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)34644e97550SJiawen Wu s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
34744e97550SJiawen Wu u32 device_type, u16 phy_data)
34844e97550SJiawen Wu {
34944e97550SJiawen Wu s32 err;
35044e97550SJiawen Wu
35144e97550SJiawen Wu err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type,
35244e97550SJiawen Wu phy_data);
35344e97550SJiawen Wu
35444e97550SJiawen Wu return err;
35544e97550SJiawen Wu }
35644e97550SJiawen Wu
35744e97550SJiawen Wu /**
35844e97550SJiawen Wu * ngbe_init_phy - PHY specific init
35944e97550SJiawen Wu * @hw: pointer to hardware structure
36044e97550SJiawen Wu *
36144e97550SJiawen Wu * Initialize any function pointers that were not able to be
36244e97550SJiawen Wu * set during init_shared_code because the PHY type was
36344e97550SJiawen Wu * not known.
36444e97550SJiawen Wu *
36544e97550SJiawen Wu **/
ngbe_init_phy(struct ngbe_hw * hw)36644e97550SJiawen Wu s32 ngbe_init_phy(struct ngbe_hw *hw)
36744e97550SJiawen Wu {
36844e97550SJiawen Wu struct ngbe_phy_info *phy = &hw->phy;
36944e97550SJiawen Wu s32 err = 0;
37044e97550SJiawen Wu
37144e97550SJiawen Wu hw->phy.addr = 0;
37244e97550SJiawen Wu
37344e97550SJiawen Wu switch (hw->sub_device_id) {
37444e97550SJiawen Wu case NGBE_SUB_DEV_ID_EM_RTL_SGMII:
3751c44384fSJiawen Wu case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP:
37644e97550SJiawen Wu hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl;
37744e97550SJiawen Wu hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl;
37844e97550SJiawen Wu break;
37944e97550SJiawen Wu case NGBE_SUB_DEV_ID_EM_MVL_RGMII:
38044e97550SJiawen Wu case NGBE_SUB_DEV_ID_EM_MVL_SFP:
3811c44384fSJiawen Wu case NGBE_SUB_DEV_ID_EM_MVL_MIX:
38244e97550SJiawen Wu hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl;
38344e97550SJiawen Wu hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl;
38444e97550SJiawen Wu break;
38544e97550SJiawen Wu case NGBE_SUB_DEV_ID_EM_YT8521S_SFP:
38644e97550SJiawen Wu hw->phy.read_reg_unlocked = ngbe_read_phy_reg_yt;
38744e97550SJiawen Wu hw->phy.write_reg_unlocked = ngbe_write_phy_reg_yt;
38844e97550SJiawen Wu break;
38944e97550SJiawen Wu default:
39044e97550SJiawen Wu break;
39144e97550SJiawen Wu }
39244e97550SJiawen Wu
39344e97550SJiawen Wu hw->phy.phy_semaphore_mask = NGBE_MNGSEM_SWPHY;
39444e97550SJiawen Wu
39544e97550SJiawen Wu /* Identify the PHY */
39644e97550SJiawen Wu err = phy->identify(hw);
3973d0af706SJiawen Wu if (err == NGBE_ERR_PHY_ADDR_INVALID)
3983d0af706SJiawen Wu goto init_phy_ops_out;
39944e97550SJiawen Wu
4003d0af706SJiawen Wu /* Set necessary function pointers based on PHY type */
4013d0af706SJiawen Wu switch (hw->phy.type) {
4023d0af706SJiawen Wu case ngbe_phy_rtl:
4033518df57SJiawen Wu hw->phy.init_hw = ngbe_init_phy_rtl;
4043d0af706SJiawen Wu hw->phy.check_link = ngbe_check_phy_link_rtl;
4053d0af706SJiawen Wu hw->phy.setup_link = ngbe_setup_phy_link_rtl;
406abea8974SJiawen Wu hw->phy.set_phy_power = ngbe_set_phy_power_rtl;
407f40e9f0eSJiawen Wu hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_rtl;
408f40e9f0eSJiawen Wu hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_rtl;
409f40e9f0eSJiawen Wu hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_rtl;
4103d0af706SJiawen Wu break;
4113d0af706SJiawen Wu case ngbe_phy_mvl:
4123d0af706SJiawen Wu case ngbe_phy_mvl_sfi:
4133518df57SJiawen Wu hw->phy.init_hw = ngbe_init_phy_mvl;
4143d0af706SJiawen Wu hw->phy.check_link = ngbe_check_phy_link_mvl;
4153d0af706SJiawen Wu hw->phy.setup_link = ngbe_setup_phy_link_mvl;
416708ebe7dSJiawen Wu hw->phy.set_phy_power = ngbe_set_phy_power_mvl;
417f40e9f0eSJiawen Wu hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_mvl;
418f40e9f0eSJiawen Wu hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_mvl;
419f40e9f0eSJiawen Wu hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_mvl;
4203d0af706SJiawen Wu break;
4213d0af706SJiawen Wu case ngbe_phy_yt8521s:
4223d0af706SJiawen Wu case ngbe_phy_yt8521s_sfi:
4233518df57SJiawen Wu hw->phy.init_hw = ngbe_init_phy_yt;
4243d0af706SJiawen Wu hw->phy.check_link = ngbe_check_phy_link_yt;
4253d0af706SJiawen Wu hw->phy.setup_link = ngbe_setup_phy_link_yt;
426708ebe7dSJiawen Wu hw->phy.set_phy_power = ngbe_set_phy_power_yt;
427f40e9f0eSJiawen Wu hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_yt;
428f40e9f0eSJiawen Wu hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_yt;
429f40e9f0eSJiawen Wu hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_yt;
4303d0af706SJiawen Wu default:
4313d0af706SJiawen Wu break;
4323d0af706SJiawen Wu }
4333d0af706SJiawen Wu
434*5f1ab0d5SJiawen Wu if (hw->wol_enabled || hw->ncsi_enabled)
435*5f1ab0d5SJiawen Wu hw->phy.reset_disable = true;
436*5f1ab0d5SJiawen Wu
4373d0af706SJiawen Wu init_phy_ops_out:
43844e97550SJiawen Wu return err;
43944e97550SJiawen Wu }
44044e97550SJiawen Wu
441