xref: /dpdk/drivers/net/ngbe/base/ngbe_phy_yt.c (revision 5f1ab0d529fce519e53d3bda32e1eeed4d61bed7)
144e97550SJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause
244e97550SJiawen Wu  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
344e97550SJiawen Wu  */
444e97550SJiawen Wu 
544e97550SJiawen Wu #include "ngbe_phy_yt.h"
644e97550SJiawen Wu 
744e97550SJiawen Wu #define YT_PHY_RST_WAIT_PERIOD		5
844e97550SJiawen Wu 
ngbe_read_phy_reg_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)944e97550SJiawen Wu s32 ngbe_read_phy_reg_yt(struct ngbe_hw *hw,
1044e97550SJiawen Wu 		u32 reg_addr, u32 device_type, u16 *phy_data)
1144e97550SJiawen Wu {
1244e97550SJiawen Wu 	mdi_reg_t reg;
1344e97550SJiawen Wu 	mdi_reg_22_t reg22;
1444e97550SJiawen Wu 
1544e97550SJiawen Wu 	reg.device_type = device_type;
1644e97550SJiawen Wu 	reg.addr = reg_addr;
1744e97550SJiawen Wu 
1844e97550SJiawen Wu 	ngbe_mdi_map_register(&reg, &reg22);
1944e97550SJiawen Wu 
2044e97550SJiawen Wu 	/* Read MII reg according to media type */
2144e97550SJiawen Wu 	if (hw->phy.media_type == ngbe_media_type_fiber) {
2244e97550SJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
2344e97550SJiawen Wu 					reg22.device_type, YT_SMI_PHY_SDS);
2444e97550SJiawen Wu 		ngbe_read_phy_reg_mdi(hw, reg22.addr,
2544e97550SJiawen Wu 					reg22.device_type, phy_data);
2644e97550SJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
2744e97550SJiawen Wu 					reg22.device_type, 0);
2844e97550SJiawen Wu 	} else {
2944e97550SJiawen Wu 		ngbe_read_phy_reg_mdi(hw, reg22.addr,
3044e97550SJiawen Wu 					reg22.device_type, phy_data);
3144e97550SJiawen Wu 	}
3244e97550SJiawen Wu 
3344e97550SJiawen Wu 	return 0;
3444e97550SJiawen Wu }
3544e97550SJiawen Wu 
ngbe_write_phy_reg_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)3644e97550SJiawen Wu s32 ngbe_write_phy_reg_yt(struct ngbe_hw *hw,
3744e97550SJiawen Wu 		u32 reg_addr, u32 device_type, u16 phy_data)
3844e97550SJiawen Wu {
3944e97550SJiawen Wu 	mdi_reg_t reg;
4044e97550SJiawen Wu 	mdi_reg_22_t reg22;
4144e97550SJiawen Wu 
4244e97550SJiawen Wu 	reg.device_type = device_type;
4344e97550SJiawen Wu 	reg.addr = reg_addr;
4444e97550SJiawen Wu 
4544e97550SJiawen Wu 	ngbe_mdi_map_register(&reg, &reg22);
4644e97550SJiawen Wu 
4744e97550SJiawen Wu 	/* Write MII reg according to media type */
4844e97550SJiawen Wu 	if (hw->phy.media_type == ngbe_media_type_fiber) {
4944e97550SJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
5044e97550SJiawen Wu 					reg22.device_type, YT_SMI_PHY_SDS);
5144e97550SJiawen Wu 		ngbe_write_phy_reg_mdi(hw, reg22.addr,
5244e97550SJiawen Wu 					reg22.device_type, phy_data);
5344e97550SJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
5444e97550SJiawen Wu 					reg22.device_type, 0);
5544e97550SJiawen Wu 	} else {
5644e97550SJiawen Wu 		ngbe_write_phy_reg_mdi(hw, reg22.addr,
5744e97550SJiawen Wu 					reg22.device_type, phy_data);
5844e97550SJiawen Wu 	}
5944e97550SJiawen Wu 
6044e97550SJiawen Wu 	return 0;
6144e97550SJiawen Wu }
6244e97550SJiawen Wu 
ngbe_read_phy_reg_ext_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)6344e97550SJiawen Wu s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw,
6444e97550SJiawen Wu 		u32 reg_addr, u32 device_type, u16 *phy_data)
6544e97550SJiawen Wu {
6644e97550SJiawen Wu 	ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
6744e97550SJiawen Wu 	ngbe_read_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
6844e97550SJiawen Wu 
6944e97550SJiawen Wu 	return 0;
7044e97550SJiawen Wu }
7144e97550SJiawen Wu 
ngbe_write_phy_reg_ext_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)7244e97550SJiawen Wu s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw,
7344e97550SJiawen Wu 		u32 reg_addr, u32 device_type, u16 phy_data)
7444e97550SJiawen Wu {
7544e97550SJiawen Wu 	ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
7644e97550SJiawen Wu 	ngbe_write_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
7744e97550SJiawen Wu 
7844e97550SJiawen Wu 	return 0;
7944e97550SJiawen Wu }
8044e97550SJiawen Wu 
ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)813d0af706SJiawen Wu s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
823d0af706SJiawen Wu 		u32 reg_addr, u32 device_type, u16 *phy_data)
833d0af706SJiawen Wu {
843d0af706SJiawen Wu 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
853d0af706SJiawen Wu 	ngbe_read_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
863d0af706SJiawen Wu 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
873d0af706SJiawen Wu 
883d0af706SJiawen Wu 	return 0;
893d0af706SJiawen Wu }
903d0af706SJiawen Wu 
ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)913d0af706SJiawen Wu s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
923d0af706SJiawen Wu 		u32 reg_addr, u32 device_type, u16 phy_data)
933d0af706SJiawen Wu {
943d0af706SJiawen Wu 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
953d0af706SJiawen Wu 	ngbe_write_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
963d0af706SJiawen Wu 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
973d0af706SJiawen Wu 
983d0af706SJiawen Wu 	return 0;
993d0af706SJiawen Wu }
1003d0af706SJiawen Wu 
ngbe_init_phy_yt(struct ngbe_hw * hw)1013518df57SJiawen Wu s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
1023518df57SJiawen Wu {
10331a28a99SJiawen Wu 	rte_spinlock_init(&hw->phy_lock);
10431a28a99SJiawen Wu 
10521f702d5SJiawen Wu 	if (hw->lsc) {
10631a28a99SJiawen Wu 		rte_spinlock_lock(&hw->phy_lock);
1071c44384fSJiawen Wu 		/* close sds area register */
1083518df57SJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
1093518df57SJiawen Wu 		/* enable interrupts */
1101c44384fSJiawen Wu 		ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
1111c44384fSJiawen Wu 					YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
11231a28a99SJiawen Wu 		rte_spinlock_unlock(&hw->phy_lock);
11321f702d5SJiawen Wu 	}
1143518df57SJiawen Wu 
115708ebe7dSJiawen Wu 	hw->phy.set_phy_power(hw, false);
1161c44384fSJiawen Wu 
1173518df57SJiawen Wu 	return 0;
1183518df57SJiawen Wu }
1193518df57SJiawen Wu 
ngbe_setup_phy_link_yt(struct ngbe_hw * hw,u32 speed,bool autoneg_wait_to_complete)1203d0af706SJiawen Wu s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
1213d0af706SJiawen Wu 				bool autoneg_wait_to_complete)
1223d0af706SJiawen Wu {
1233d0af706SJiawen Wu 	u16 value_r4 = 0;
1243d0af706SJiawen Wu 	u16 value_r9 = 0;
1253d0af706SJiawen Wu 	u16 value;
1263d0af706SJiawen Wu 
1273d0af706SJiawen Wu 	UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
1283d0af706SJiawen Wu 
129*5f1ab0d5SJiawen Wu 	if (hw->ncsi_enabled)
130*5f1ab0d5SJiawen Wu 		return 0;
131*5f1ab0d5SJiawen Wu 
1323d0af706SJiawen Wu 	hw->phy.autoneg_advertised = 0;
1333d0af706SJiawen Wu 
1341c44384fSJiawen Wu 	/* check chip_mode first */
13531a28a99SJiawen Wu 	rte_spinlock_lock(&hw->phy_lock);
1361c44384fSJiawen Wu 	ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
13731a28a99SJiawen Wu 	rte_spinlock_unlock(&hw->phy_lock);
1381c44384fSJiawen Wu 	if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(0)) {
1391c44384fSJiawen Wu 		/* UTP to rgmii */
1401c44384fSJiawen Wu 		if (!hw->mac.autoneg) {
1411c44384fSJiawen Wu 			switch (speed) {
1421c44384fSJiawen Wu 			case NGBE_LINK_SPEED_1GB_FULL:
1431c44384fSJiawen Wu 				value = YT_BCR_SPEED_SELECT1;
1441c44384fSJiawen Wu 				break;
1451c44384fSJiawen Wu 			case NGBE_LINK_SPEED_100M_FULL:
1461c44384fSJiawen Wu 				value = YT_BCR_SPEED_SELECT0;
1471c44384fSJiawen Wu 				break;
1481c44384fSJiawen Wu 			case NGBE_LINK_SPEED_10M_FULL:
1491c44384fSJiawen Wu 				value = 0;
1501c44384fSJiawen Wu 				break;
1511c44384fSJiawen Wu 			default:
1521c44384fSJiawen Wu 				value = YT_BCR_SPEED_SELECT0 |
1531c44384fSJiawen Wu 					YT_BCR_SPEED_SELECT1;
154c811e6a4SJiawen Wu 				DEBUGOUT("unknown speed = 0x%x.",
1551c44384fSJiawen Wu 					speed);
1561c44384fSJiawen Wu 				break;
1571c44384fSJiawen Wu 			}
1581c44384fSJiawen Wu 			/* duplex full */
1591c44384fSJiawen Wu 			value |= YT_BCR_DUPLEX | YT_BCR_RESET;
16031a28a99SJiawen Wu 			rte_spinlock_lock(&hw->phy_lock);
16100f9e5c7SJiawen Wu 			ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
16231a28a99SJiawen Wu 			rte_spinlock_unlock(&hw->phy_lock);
1631c44384fSJiawen Wu 
1641c44384fSJiawen Wu 			goto skip_an;
1651c44384fSJiawen Wu 		}
1661c44384fSJiawen Wu 
16731a28a99SJiawen Wu 		rte_spinlock_lock(&hw->phy_lock);
1683d0af706SJiawen Wu 		/*disable 100/10base-T Self-negotiation ability*/
16900f9e5c7SJiawen Wu 		ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
1701c44384fSJiawen Wu 		value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
1711c44384fSJiawen Wu 			YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
17200f9e5c7SJiawen Wu 		ngbe_write_phy_reg_mdi(hw, YT_ANA, 0, value);
1733d0af706SJiawen Wu 
1743d0af706SJiawen Wu 		/*disable 1000base-T Self-negotiation ability*/
17500f9e5c7SJiawen Wu 		ngbe_read_phy_reg_mdi(hw, YT_MS_CTRL, 0, &value);
1761c44384fSJiawen Wu 		value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
17700f9e5c7SJiawen Wu 		ngbe_write_phy_reg_mdi(hw, YT_MS_CTRL, 0, value);
1783d0af706SJiawen Wu 
1793d0af706SJiawen Wu 		if (speed & NGBE_LINK_SPEED_1GB_FULL) {
1803d0af706SJiawen Wu 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
1813d0af706SJiawen Wu 			value_r9 |= YT_MS_1000BASET_FULL;
1823d0af706SJiawen Wu 		}
1833d0af706SJiawen Wu 		if (speed & NGBE_LINK_SPEED_100M_FULL) {
1843d0af706SJiawen Wu 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
1853d0af706SJiawen Wu 			value_r4 |= YT_ANA_100BASET_FULL;
1863d0af706SJiawen Wu 		}
1873d0af706SJiawen Wu 		if (speed & NGBE_LINK_SPEED_10M_FULL) {
1883d0af706SJiawen Wu 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
1893d0af706SJiawen Wu 			value_r4 |= YT_ANA_10BASET_FULL;
1903d0af706SJiawen Wu 		}
1913d0af706SJiawen Wu 
1923d0af706SJiawen Wu 		/* enable 1000base-T Self-negotiation ability */
19300f9e5c7SJiawen Wu 		ngbe_read_phy_reg_mdi(hw, YT_MS_CTRL, 0, &value);
1943d0af706SJiawen Wu 		value |= value_r9;
19500f9e5c7SJiawen Wu 		ngbe_write_phy_reg_mdi(hw, YT_MS_CTRL, 0, value);
1963d0af706SJiawen Wu 
1973d0af706SJiawen Wu 		/* enable 100/10base-T Self-negotiation ability */
19800f9e5c7SJiawen Wu 		ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
1993d0af706SJiawen Wu 		value |= value_r4;
20000f9e5c7SJiawen Wu 		ngbe_write_phy_reg_mdi(hw, YT_ANA, 0, value);
2013d0af706SJiawen Wu 
2023d0af706SJiawen Wu 		/* software reset to make the above configuration take effect*/
20300f9e5c7SJiawen Wu 		ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
2041c44384fSJiawen Wu 		value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
20500f9e5c7SJiawen Wu 		ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
20631a28a99SJiawen Wu 		rte_spinlock_unlock(&hw->phy_lock);
2071c44384fSJiawen Wu skip_an:
208708ebe7dSJiawen Wu 		hw->phy.set_phy_power(hw, true);
2091c44384fSJiawen Wu 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1)) {
2101c44384fSJiawen Wu 		/* fiber to rgmii */
211930a3bd4SJiawen Wu 		if (!hw->mac.autoneg) {
212930a3bd4SJiawen Wu 			switch (speed) {
213930a3bd4SJiawen Wu 			case NGBE_LINK_SPEED_1GB_FULL:
214930a3bd4SJiawen Wu 				value = NGBE_LINK_SPEED_1GB_FULL;
215930a3bd4SJiawen Wu 				break;
216930a3bd4SJiawen Wu 			case NGBE_LINK_SPEED_100M_FULL:
217930a3bd4SJiawen Wu 				value = NGBE_LINK_SPEED_100M_FULL;
218930a3bd4SJiawen Wu 				break;
219930a3bd4SJiawen Wu 			default:
220930a3bd4SJiawen Wu 				value = NGBE_LINK_SPEED_1GB_FULL;
221930a3bd4SJiawen Wu 				break;
222930a3bd4SJiawen Wu 			}
223930a3bd4SJiawen Wu 			hw->phy.autoneg_advertised |= value;
224930a3bd4SJiawen Wu 			goto skip_an_fiber;
225930a3bd4SJiawen Wu 		}
226930a3bd4SJiawen Wu 
227930a3bd4SJiawen Wu 		value = 0;
228930a3bd4SJiawen Wu 		if (speed & NGBE_LINK_SPEED_1GB_FULL)
2293d0af706SJiawen Wu 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
230930a3bd4SJiawen Wu 		if (speed & NGBE_LINK_SPEED_100M_FULL)
231930a3bd4SJiawen Wu 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
232930a3bd4SJiawen Wu 
233930a3bd4SJiawen Wu skip_an_fiber:
234930a3bd4SJiawen Wu 		rte_spinlock_lock(&hw->phy_lock);
235930a3bd4SJiawen Wu 		ngbe_read_phy_reg_ext_yt(hw, YT_MISC, 0, &value);
236930a3bd4SJiawen Wu 		if (hw->phy.autoneg_advertised & NGBE_LINK_SPEED_1GB_FULL)
237930a3bd4SJiawen Wu 			value |= YT_MISC_RESV;
238930a3bd4SJiawen Wu 		else if (hw->phy.autoneg_advertised & NGBE_LINK_SPEED_100M_FULL)
239930a3bd4SJiawen Wu 			value &= ~YT_MISC_RESV;
240930a3bd4SJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_MISC, 0, value);
241930a3bd4SJiawen Wu 
242930a3bd4SJiawen Wu 		/* close auto sensing */
243930a3bd4SJiawen Wu 		ngbe_read_phy_reg_sds_ext_yt(hw, YT_AUTO, 0, &value);
244930a3bd4SJiawen Wu 		value &= ~YT_AUTO_SENSING;
245930a3bd4SJiawen Wu 		ngbe_write_phy_reg_sds_ext_yt(hw, YT_AUTO, 0, value);
246930a3bd4SJiawen Wu 
247930a3bd4SJiawen Wu 		ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
248930a3bd4SJiawen Wu 		value &= ~YT_CHIP_SW_RST;
249930a3bd4SJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
2503d0af706SJiawen Wu 
2513d0af706SJiawen Wu 		/* RGMII_Config1 : Config rx and tx training delay */
2523d0af706SJiawen Wu 		value = YT_RGMII_CONF1_RXDELAY |
2533d0af706SJiawen Wu 			YT_RGMII_CONF1_TXDELAY_FE |
2543d0af706SJiawen Wu 			YT_RGMII_CONF1_TXDELAY;
255930a3bd4SJiawen Wu 
2563d0af706SJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
2573d0af706SJiawen Wu 		value = YT_CHIP_MODE_SEL(1) |
2583d0af706SJiawen Wu 			YT_CHIP_SW_LDO_EN |
2593d0af706SJiawen Wu 			YT_CHIP_SW_RST;
2603d0af706SJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
2613d0af706SJiawen Wu 
2623d0af706SJiawen Wu 		/* software reset */
263930a3bd4SJiawen Wu 		if (hw->mac.autoneg) {
264f1268369SJiawen Wu 			value = YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN |
265f1268369SJiawen Wu 				YT_BCR_DUPLEX | YT_BCR_SPEED_SELECT1;
266930a3bd4SJiawen Wu 		} else {
267930a3bd4SJiawen Wu 			value = YT_BCR_RESET | YT_BCR_DUPLEX;
268930a3bd4SJiawen Wu 			if (speed & NGBE_LINK_SPEED_1GB_FULL)
269930a3bd4SJiawen Wu 				value |= YT_BCR_SPEED_SELECT1;
270930a3bd4SJiawen Wu 			if (speed & NGBE_LINK_SPEED_100M_FULL)
271930a3bd4SJiawen Wu 				value |= YT_BCR_SPEED_SELECT0;
272930a3bd4SJiawen Wu 		}
273f1268369SJiawen Wu 		hw->phy.write_reg(hw, YT_BCR, 0, value);
27431a28a99SJiawen Wu 		rte_spinlock_unlock(&hw->phy_lock);
2753d0af706SJiawen Wu 
276708ebe7dSJiawen Wu 		hw->phy.set_phy_power(hw, true);
2771c44384fSJiawen Wu 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(2)) {
278708ebe7dSJiawen Wu 		hw->phy.set_phy_power(hw, true);
2791c44384fSJiawen Wu 
28031a28a99SJiawen Wu 		rte_spinlock_lock(&hw->phy_lock);
2811c44384fSJiawen Wu 		hw->phy.read_reg(hw, YT_SPST, 0, &value);
28231a28a99SJiawen Wu 		rte_spinlock_unlock(&hw->phy_lock);
2831c44384fSJiawen Wu 		if (value & YT_SPST_LINK) {
2841c44384fSJiawen Wu 			/* fiber up */
2851c44384fSJiawen Wu 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
2861c44384fSJiawen Wu 		} else {
2871c44384fSJiawen Wu 			/* utp up */
28831a28a99SJiawen Wu 			rte_spinlock_lock(&hw->phy_lock);
2891c44384fSJiawen Wu 			/*disable 100/10base-T Self-negotiation ability*/
29000f9e5c7SJiawen Wu 			ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
2911c44384fSJiawen Wu 			value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
2921c44384fSJiawen Wu 				YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
29300f9e5c7SJiawen Wu 			ngbe_write_phy_reg_mdi(hw, YT_ANA, 0, value);
2941c44384fSJiawen Wu 
2951c44384fSJiawen Wu 			/*disable 1000base-T Self-negotiation ability*/
29600f9e5c7SJiawen Wu 			ngbe_read_phy_reg_mdi(hw, YT_MS_CTRL, 0, &value);
2971c44384fSJiawen Wu 			value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
29800f9e5c7SJiawen Wu 			ngbe_write_phy_reg_mdi(hw, YT_MS_CTRL, 0, value);
2991c44384fSJiawen Wu 
3001c44384fSJiawen Wu 			if (speed & NGBE_LINK_SPEED_1GB_FULL) {
3011c44384fSJiawen Wu 				hw->phy.autoneg_advertised |=
3021c44384fSJiawen Wu 						NGBE_LINK_SPEED_1GB_FULL;
3031c44384fSJiawen Wu 				value_r9 |= YT_MS_1000BASET_FULL;
3041c44384fSJiawen Wu 			}
3051c44384fSJiawen Wu 			if (speed & NGBE_LINK_SPEED_100M_FULL) {
3061c44384fSJiawen Wu 				hw->phy.autoneg_advertised |=
3071c44384fSJiawen Wu 						NGBE_LINK_SPEED_100M_FULL;
3081c44384fSJiawen Wu 				value_r4 |= YT_ANA_100BASET_FULL;
3091c44384fSJiawen Wu 			}
3101c44384fSJiawen Wu 			if (speed & NGBE_LINK_SPEED_10M_FULL) {
3111c44384fSJiawen Wu 				hw->phy.autoneg_advertised |=
3121c44384fSJiawen Wu 						NGBE_LINK_SPEED_10M_FULL;
3131c44384fSJiawen Wu 				value_r4 |= YT_ANA_10BASET_FULL;
3141c44384fSJiawen Wu 			}
3151c44384fSJiawen Wu 
3161c44384fSJiawen Wu 			/* enable 1000base-T Self-negotiation ability */
31700f9e5c7SJiawen Wu 			ngbe_read_phy_reg_mdi(hw, YT_MS_CTRL, 0, &value);
3181c44384fSJiawen Wu 			value |= value_r9;
31900f9e5c7SJiawen Wu 			ngbe_write_phy_reg_mdi(hw, YT_MS_CTRL, 0, value);
3201c44384fSJiawen Wu 
3211c44384fSJiawen Wu 			/* enable 100/10base-T Self-negotiation ability */
32200f9e5c7SJiawen Wu 			ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
3231c44384fSJiawen Wu 			value |= value_r4;
32400f9e5c7SJiawen Wu 			ngbe_write_phy_reg_mdi(hw, YT_ANA, 0, value);
3251c44384fSJiawen Wu 
32679be49ddSJiawen Wu 			/* config for yt8531sh-ca */
32779be49ddSJiawen Wu 			ngbe_write_phy_reg_ext_yt(hw, YT_SPEC_CONF, 0,
32879be49ddSJiawen Wu 						YT_SPEC_CONF_8531SH_CA);
32979be49ddSJiawen Wu 
3301c44384fSJiawen Wu 			/* software reset to make the above configuration
3311c44384fSJiawen Wu 			 * take effect
3321c44384fSJiawen Wu 			 */
33300f9e5c7SJiawen Wu 			ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
3341c44384fSJiawen Wu 			value |= YT_BCR_RESET;
33500f9e5c7SJiawen Wu 			ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
33631a28a99SJiawen Wu 			rte_spinlock_unlock(&hw->phy_lock);
3371c44384fSJiawen Wu 		}
3381c44384fSJiawen Wu 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(4)) {
3391c44384fSJiawen Wu 		hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
3401c44384fSJiawen Wu 
34131a28a99SJiawen Wu 		rte_spinlock_lock(&hw->phy_lock);
3421c44384fSJiawen Wu 		ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, &value);
3431c44384fSJiawen Wu 		value |= YT_RGMII_CONF1_MODE;
3441c44384fSJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
3451c44384fSJiawen Wu 
3461c44384fSJiawen Wu 		ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, &value);
3471c44384fSJiawen Wu 		value &= ~(YT_RGMII_CONF2_SPEED_MASK | YT_RGMII_CONF2_DUPLEX |
3481c44384fSJiawen Wu 			YT_RGMII_CONF2_LINKUP);
3491c44384fSJiawen Wu 		value |= YT_RGMII_CONF2_SPEED(2) | YT_RGMII_CONF2_DUPLEX |
3501c44384fSJiawen Wu 			YT_RGMII_CONF2_LINKUP;
3511c44384fSJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, value);
3521c44384fSJiawen Wu 
3531c44384fSJiawen Wu 		ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
3541c44384fSJiawen Wu 		value &= ~YT_SMI_PHY_SW_RST;
3551c44384fSJiawen Wu 		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
35631a28a99SJiawen Wu 		rte_spinlock_unlock(&hw->phy_lock);
3571c44384fSJiawen Wu 
358708ebe7dSJiawen Wu 		hw->phy.set_phy_power(hw, true);
35969033e3bSJiawen Wu 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(5)) {
36069033e3bSJiawen Wu 		/* sgmii_to_rgmii */
36169033e3bSJiawen Wu 		if (!hw->mac.autoneg) {
36269033e3bSJiawen Wu 			switch (speed) {
36369033e3bSJiawen Wu 			case NGBE_LINK_SPEED_1GB_FULL:
36469033e3bSJiawen Wu 				value = YT_BCR_SPEED_SELECT1;
36569033e3bSJiawen Wu 				break;
36669033e3bSJiawen Wu 			case NGBE_LINK_SPEED_100M_FULL:
36769033e3bSJiawen Wu 				value = YT_BCR_SPEED_SELECT0;
36869033e3bSJiawen Wu 				break;
36969033e3bSJiawen Wu 			case NGBE_LINK_SPEED_10M_FULL:
37069033e3bSJiawen Wu 				value = 0;
37169033e3bSJiawen Wu 				break;
37269033e3bSJiawen Wu 			default:
37369033e3bSJiawen Wu 				value = YT_BCR_SPEED_SELECT0 |
37469033e3bSJiawen Wu 					YT_BCR_SPEED_SELECT1;
37569033e3bSJiawen Wu 				DEBUGOUT("unknown speed = 0x%x", speed);
37669033e3bSJiawen Wu 				break;
37769033e3bSJiawen Wu 			}
37869033e3bSJiawen Wu 			/* duplex full */
37969033e3bSJiawen Wu 			value |= YT_BCR_DUPLEX | YT_BCR_RESET;
38031a28a99SJiawen Wu 			rte_spinlock_lock(&hw->phy_lock);
38169033e3bSJiawen Wu 			hw->phy.write_reg(hw, YT_BCR, 0, value);
38231a28a99SJiawen Wu 			rte_spinlock_unlock(&hw->phy_lock);
38369033e3bSJiawen Wu 
38469033e3bSJiawen Wu 			goto skip_an_sr;
38569033e3bSJiawen Wu 		}
38669033e3bSJiawen Wu 
38769033e3bSJiawen Wu 		value = 0;
38869033e3bSJiawen Wu 		if (speed & NGBE_LINK_SPEED_1GB_FULL) {
38969033e3bSJiawen Wu 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
39069033e3bSJiawen Wu 			value |= YT_BCR_SPEED_SELECT1;
39169033e3bSJiawen Wu 		}
39269033e3bSJiawen Wu 		if (speed & NGBE_LINK_SPEED_100M_FULL) {
39369033e3bSJiawen Wu 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
39469033e3bSJiawen Wu 			value |= YT_BCR_SPEED_SELECT0;
39569033e3bSJiawen Wu 		}
39669033e3bSJiawen Wu 		if (speed & NGBE_LINK_SPEED_10M_FULL)
39769033e3bSJiawen Wu 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
39869033e3bSJiawen Wu 
39969033e3bSJiawen Wu 		/* duplex full */
40069033e3bSJiawen Wu 		value |= YT_BCR_DUPLEX | YT_BCR_RESET;
40131a28a99SJiawen Wu 		rte_spinlock_lock(&hw->phy_lock);
40269033e3bSJiawen Wu 		hw->phy.write_reg(hw, YT_BCR, 0, value);
40369033e3bSJiawen Wu 
40469033e3bSJiawen Wu 		/* software reset to make the above configuration take effect */
40569033e3bSJiawen Wu 		hw->phy.read_reg(hw, YT_BCR, 0, &value);
40669033e3bSJiawen Wu 		value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
40769033e3bSJiawen Wu 		hw->phy.write_reg(hw, 0x0, 0, value);
40831a28a99SJiawen Wu 		rte_spinlock_unlock(&hw->phy_lock);
40969033e3bSJiawen Wu 
41069033e3bSJiawen Wu skip_an_sr:
41169033e3bSJiawen Wu 		hw->phy.set_phy_power(hw, true);
4123d0af706SJiawen Wu 	}
4133d0af706SJiawen Wu 
41431a28a99SJiawen Wu 	rte_spinlock_lock(&hw->phy_lock);
4153d0af706SJiawen Wu 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
4163d0af706SJiawen Wu 	ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
41731a28a99SJiawen Wu 	rte_spinlock_unlock(&hw->phy_lock);
4183d0af706SJiawen Wu 
4193d0af706SJiawen Wu 	return 0;
4203d0af706SJiawen Wu }
4213d0af706SJiawen Wu 
ngbe_reset_phy_yt(struct ngbe_hw * hw)42244e97550SJiawen Wu s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
42344e97550SJiawen Wu {
42444e97550SJiawen Wu 	u32 i;
42544e97550SJiawen Wu 	u16 ctrl = 0;
42644e97550SJiawen Wu 	s32 status = 0;
42744e97550SJiawen Wu 
42844e97550SJiawen Wu 	if (hw->phy.type != ngbe_phy_yt8521s &&
42944e97550SJiawen Wu 		hw->phy.type != ngbe_phy_yt8521s_sfi)
43044e97550SJiawen Wu 		return NGBE_ERR_PHY_TYPE;
43144e97550SJiawen Wu 
43231a28a99SJiawen Wu 	rte_spinlock_lock(&hw->phy_lock);
4331c44384fSJiawen Wu 	/* check chip_mode first */
4341c44384fSJiawen Wu 	ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &ctrl);
4351c44384fSJiawen Wu 	if (ctrl & YT_CHIP_MODE_MASK) {
4361c44384fSJiawen Wu 		/* fiber to rgmii */
43744e97550SJiawen Wu 		status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
43844e97550SJiawen Wu 		/* sds software reset */
43944e97550SJiawen Wu 		ctrl |= YT_BCR_RESET;
44044e97550SJiawen Wu 		status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
44144e97550SJiawen Wu 
44244e97550SJiawen Wu 		for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
44344e97550SJiawen Wu 			status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
44444e97550SJiawen Wu 			if (!(ctrl & YT_BCR_RESET))
44544e97550SJiawen Wu 				break;
44644e97550SJiawen Wu 			msleep(1);
44744e97550SJiawen Wu 		}
4481c44384fSJiawen Wu 	} else {
4491c44384fSJiawen Wu 		/* UTP to rgmii */
4501c44384fSJiawen Wu 		status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
4511c44384fSJiawen Wu 		/* sds software reset */
4521c44384fSJiawen Wu 		ctrl |= YT_BCR_RESET;
4531c44384fSJiawen Wu 		status = ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, ctrl);
4541c44384fSJiawen Wu 
4551c44384fSJiawen Wu 		for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
4561c44384fSJiawen Wu 			status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
4571c44384fSJiawen Wu 			if (!(ctrl & YT_BCR_RESET))
4581c44384fSJiawen Wu 				break;
4591c44384fSJiawen Wu 			msleep(1);
4601c44384fSJiawen Wu 		}
4611c44384fSJiawen Wu 	}
46231a28a99SJiawen Wu 	rte_spinlock_unlock(&hw->phy_lock);
46344e97550SJiawen Wu 
46444e97550SJiawen Wu 	if (i == YT_PHY_RST_WAIT_PERIOD) {
465c811e6a4SJiawen Wu 		DEBUGOUT("PHY reset polling failed to complete.");
46644e97550SJiawen Wu 		return NGBE_ERR_RESET_FAILED;
46744e97550SJiawen Wu 	}
46844e97550SJiawen Wu 
46944e97550SJiawen Wu 	return status;
47044e97550SJiawen Wu }
47144e97550SJiawen Wu 
ngbe_get_phy_advertised_pause_yt(struct ngbe_hw * hw,u8 * pause_bit)472f40e9f0eSJiawen Wu s32 ngbe_get_phy_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
473f40e9f0eSJiawen Wu {
474f40e9f0eSJiawen Wu 	u16 value;
475f40e9f0eSJiawen Wu 	s32 status = 0;
476f40e9f0eSJiawen Wu 
47731a28a99SJiawen Wu 	rte_spinlock_lock(&hw->phy_lock);
478f40e9f0eSJiawen Wu 	status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
47931a28a99SJiawen Wu 	rte_spinlock_unlock(&hw->phy_lock);
480f40e9f0eSJiawen Wu 	value &= YT_FANA_PAUSE_MASK;
481f40e9f0eSJiawen Wu 	*pause_bit = (u8)(value >> 7);
482f40e9f0eSJiawen Wu 
483f40e9f0eSJiawen Wu 	return status;
484f40e9f0eSJiawen Wu }
485f40e9f0eSJiawen Wu 
ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw * hw,u8 * pause_bit)486f40e9f0eSJiawen Wu s32 ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
487f40e9f0eSJiawen Wu {
488f40e9f0eSJiawen Wu 	u16 value;
489f40e9f0eSJiawen Wu 	s32 status = 0;
490f40e9f0eSJiawen Wu 
49131a28a99SJiawen Wu 	rte_spinlock_lock(&hw->phy_lock);
492f40e9f0eSJiawen Wu 	status = hw->phy.read_reg(hw, YT_LPAR, 0, &value);
49331a28a99SJiawen Wu 	rte_spinlock_unlock(&hw->phy_lock);
494f40e9f0eSJiawen Wu 	value &= YT_FLPAR_PAUSE_MASK;
495f40e9f0eSJiawen Wu 	*pause_bit = (u8)(value >> 7);
496f40e9f0eSJiawen Wu 
497f40e9f0eSJiawen Wu 	return status;
498f40e9f0eSJiawen Wu }
499f40e9f0eSJiawen Wu 
ngbe_set_phy_pause_adv_yt(struct ngbe_hw * hw,u16 pause_bit)500f40e9f0eSJiawen Wu s32 ngbe_set_phy_pause_adv_yt(struct ngbe_hw *hw, u16 pause_bit)
501f40e9f0eSJiawen Wu {
502f40e9f0eSJiawen Wu 	u16 value;
503f40e9f0eSJiawen Wu 	s32 status = 0;
504f40e9f0eSJiawen Wu 
50531a28a99SJiawen Wu 	rte_spinlock_lock(&hw->phy_lock);
506f40e9f0eSJiawen Wu 	status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
507f40e9f0eSJiawen Wu 	value &= ~YT_FANA_PAUSE_MASK;
508f40e9f0eSJiawen Wu 	value |= pause_bit;
509f40e9f0eSJiawen Wu 	status = hw->phy.write_reg(hw, YT_ANA, 0, value);
51031a28a99SJiawen Wu 	rte_spinlock_unlock(&hw->phy_lock);
511f40e9f0eSJiawen Wu 
512f40e9f0eSJiawen Wu 	return status;
513f40e9f0eSJiawen Wu }
514f40e9f0eSJiawen Wu 
ngbe_check_phy_link_yt(struct ngbe_hw * hw,u32 * speed,bool * link_up)5153d0af706SJiawen Wu s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
5163d0af706SJiawen Wu 		u32 *speed, bool *link_up)
5173d0af706SJiawen Wu {
5183d0af706SJiawen Wu 	s32 status = 0;
5193d0af706SJiawen Wu 	u16 phy_link = 0;
5203d0af706SJiawen Wu 	u16 phy_speed = 0;
5213d0af706SJiawen Wu 	u16 phy_data = 0;
5223d0af706SJiawen Wu 	u16 insr = 0;
5233d0af706SJiawen Wu 
5243d0af706SJiawen Wu 	/* Initialize speed and link to default case */
5253d0af706SJiawen Wu 	*link_up = false;
5263d0af706SJiawen Wu 	*speed = NGBE_LINK_SPEED_UNKNOWN;
52731a28a99SJiawen Wu 	rte_spinlock_lock(&hw->phy_lock);
5283d0af706SJiawen Wu 
5293d0af706SJiawen Wu 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
5303d0af706SJiawen Wu 	ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
5313d0af706SJiawen Wu 
5323d0af706SJiawen Wu 	status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data);
5333d0af706SJiawen Wu 	phy_link = phy_data & YT_SPST_LINK;
5343d0af706SJiawen Wu 	phy_speed = phy_data & YT_SPST_SPEED_MASK;
5353d0af706SJiawen Wu 
5363d0af706SJiawen Wu 	if (phy_link) {
5373d0af706SJiawen Wu 		*link_up = true;
5387fa2495bSJiawen Wu 	} else {
5397fa2495bSJiawen Wu 		status = ngbe_read_phy_reg_mdi(hw, YT_SPST, 0, &phy_data);
5407fa2495bSJiawen Wu 		phy_link = phy_data & YT_SPST_LINK;
5417fa2495bSJiawen Wu 		phy_speed = phy_data & YT_SPST_SPEED_MASK;
5423d0af706SJiawen Wu 
5437fa2495bSJiawen Wu 		if (phy_link)
5447fa2495bSJiawen Wu 			*link_up = true;
5457fa2495bSJiawen Wu 	}
5467fa2495bSJiawen Wu 
54731a28a99SJiawen Wu 	rte_spinlock_unlock(&hw->phy_lock);
5487fa2495bSJiawen Wu 	if (*link_up) {
5493d0af706SJiawen Wu 		if (phy_speed == YT_SPST_SPEED_1000M)
5503d0af706SJiawen Wu 			*speed = NGBE_LINK_SPEED_1GB_FULL;
5513d0af706SJiawen Wu 		else if (phy_speed == YT_SPST_SPEED_100M)
5523d0af706SJiawen Wu 			*speed = NGBE_LINK_SPEED_100M_FULL;
5533d0af706SJiawen Wu 		else if (phy_speed == YT_SPST_SPEED_10M)
5543d0af706SJiawen Wu 			*speed = NGBE_LINK_SPEED_10M_FULL;
5553d0af706SJiawen Wu 	}
5563d0af706SJiawen Wu 
5573d0af706SJiawen Wu 	return status;
5583d0af706SJiawen Wu }
5593d0af706SJiawen Wu 
ngbe_set_phy_power_yt(struct ngbe_hw * hw,bool on)560708ebe7dSJiawen Wu s32 ngbe_set_phy_power_yt(struct ngbe_hw *hw, bool on)
561708ebe7dSJiawen Wu {
562708ebe7dSJiawen Wu 	u16 value = 0;
563708ebe7dSJiawen Wu 
56431a28a99SJiawen Wu 	rte_spinlock_lock(&hw->phy_lock);
565708ebe7dSJiawen Wu 	/* power down/up in fiber mode */
566708ebe7dSJiawen Wu 	hw->phy.read_reg(hw, YT_BCR, 0, &value);
567708ebe7dSJiawen Wu 	if (on)
568708ebe7dSJiawen Wu 		value &= ~YT_BCR_PWDN;
569708ebe7dSJiawen Wu 	else
570708ebe7dSJiawen Wu 		value |= YT_BCR_PWDN;
571708ebe7dSJiawen Wu 	hw->phy.write_reg(hw, YT_BCR, 0, value);
572708ebe7dSJiawen Wu 
573708ebe7dSJiawen Wu 	value = 0;
574708ebe7dSJiawen Wu 	/* power down/up in UTP mode */
575708ebe7dSJiawen Wu 	ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
576708ebe7dSJiawen Wu 	if (on)
577708ebe7dSJiawen Wu 		value &= ~YT_BCR_PWDN;
578708ebe7dSJiawen Wu 	else
579708ebe7dSJiawen Wu 		value |= YT_BCR_PWDN;
580708ebe7dSJiawen Wu 	ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
58131a28a99SJiawen Wu 	rte_spinlock_unlock(&hw->phy_lock);
582708ebe7dSJiawen Wu 
583708ebe7dSJiawen Wu 	return 0;
584708ebe7dSJiawen Wu }
585