xref: /dpdk/drivers/net/ngbe/base/ngbe_phy.c (revision 5f1ab0d529fce519e53d3bda32e1eeed4d61bed7)
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