xref: /dpdk/drivers/net/ngbe/base/ngbe_phy_yt.c (revision 5f1ab0d529fce519e53d3bda32e1eeed4d61bed7)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  */
4 
5 #include "ngbe_phy_yt.h"
6 
7 #define YT_PHY_RST_WAIT_PERIOD		5
8 
ngbe_read_phy_reg_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)9 s32 ngbe_read_phy_reg_yt(struct ngbe_hw *hw,
10 		u32 reg_addr, u32 device_type, u16 *phy_data)
11 {
12 	mdi_reg_t reg;
13 	mdi_reg_22_t reg22;
14 
15 	reg.device_type = device_type;
16 	reg.addr = reg_addr;
17 
18 	ngbe_mdi_map_register(&reg, &reg22);
19 
20 	/* Read MII reg according to media type */
21 	if (hw->phy.media_type == ngbe_media_type_fiber) {
22 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
23 					reg22.device_type, YT_SMI_PHY_SDS);
24 		ngbe_read_phy_reg_mdi(hw, reg22.addr,
25 					reg22.device_type, phy_data);
26 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
27 					reg22.device_type, 0);
28 	} else {
29 		ngbe_read_phy_reg_mdi(hw, reg22.addr,
30 					reg22.device_type, phy_data);
31 	}
32 
33 	return 0;
34 }
35 
ngbe_write_phy_reg_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)36 s32 ngbe_write_phy_reg_yt(struct ngbe_hw *hw,
37 		u32 reg_addr, u32 device_type, u16 phy_data)
38 {
39 	mdi_reg_t reg;
40 	mdi_reg_22_t reg22;
41 
42 	reg.device_type = device_type;
43 	reg.addr = reg_addr;
44 
45 	ngbe_mdi_map_register(&reg, &reg22);
46 
47 	/* Write MII reg according to media type */
48 	if (hw->phy.media_type == ngbe_media_type_fiber) {
49 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
50 					reg22.device_type, YT_SMI_PHY_SDS);
51 		ngbe_write_phy_reg_mdi(hw, reg22.addr,
52 					reg22.device_type, phy_data);
53 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
54 					reg22.device_type, 0);
55 	} else {
56 		ngbe_write_phy_reg_mdi(hw, reg22.addr,
57 					reg22.device_type, phy_data);
58 	}
59 
60 	return 0;
61 }
62 
ngbe_read_phy_reg_ext_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)63 s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw,
64 		u32 reg_addr, u32 device_type, u16 *phy_data)
65 {
66 	ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
67 	ngbe_read_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
68 
69 	return 0;
70 }
71 
ngbe_write_phy_reg_ext_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)72 s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw,
73 		u32 reg_addr, u32 device_type, u16 phy_data)
74 {
75 	ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
76 	ngbe_write_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
77 
78 	return 0;
79 }
80 
ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 * phy_data)81 s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
82 		u32 reg_addr, u32 device_type, u16 *phy_data)
83 {
84 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
85 	ngbe_read_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
86 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
87 
88 	return 0;
89 }
90 
ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw * hw,u32 reg_addr,u32 device_type,u16 phy_data)91 s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
92 		u32 reg_addr, u32 device_type, u16 phy_data)
93 {
94 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
95 	ngbe_write_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
96 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
97 
98 	return 0;
99 }
100 
ngbe_init_phy_yt(struct ngbe_hw * hw)101 s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
102 {
103 	rte_spinlock_init(&hw->phy_lock);
104 
105 	if (hw->lsc) {
106 		rte_spinlock_lock(&hw->phy_lock);
107 		/* close sds area register */
108 		ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
109 		/* enable interrupts */
110 		ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
111 					YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
112 		rte_spinlock_unlock(&hw->phy_lock);
113 	}
114 
115 	hw->phy.set_phy_power(hw, false);
116 
117 	return 0;
118 }
119 
ngbe_setup_phy_link_yt(struct ngbe_hw * hw,u32 speed,bool autoneg_wait_to_complete)120 s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
121 				bool autoneg_wait_to_complete)
122 {
123 	u16 value_r4 = 0;
124 	u16 value_r9 = 0;
125 	u16 value;
126 
127 	UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
128 
129 	if (hw->ncsi_enabled)
130 		return 0;
131 
132 	hw->phy.autoneg_advertised = 0;
133 
134 	/* check chip_mode first */
135 	rte_spinlock_lock(&hw->phy_lock);
136 	ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
137 	rte_spinlock_unlock(&hw->phy_lock);
138 	if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(0)) {
139 		/* UTP to rgmii */
140 		if (!hw->mac.autoneg) {
141 			switch (speed) {
142 			case NGBE_LINK_SPEED_1GB_FULL:
143 				value = YT_BCR_SPEED_SELECT1;
144 				break;
145 			case NGBE_LINK_SPEED_100M_FULL:
146 				value = YT_BCR_SPEED_SELECT0;
147 				break;
148 			case NGBE_LINK_SPEED_10M_FULL:
149 				value = 0;
150 				break;
151 			default:
152 				value = YT_BCR_SPEED_SELECT0 |
153 					YT_BCR_SPEED_SELECT1;
154 				DEBUGOUT("unknown speed = 0x%x.",
155 					speed);
156 				break;
157 			}
158 			/* duplex full */
159 			value |= YT_BCR_DUPLEX | YT_BCR_RESET;
160 			rte_spinlock_lock(&hw->phy_lock);
161 			ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
162 			rte_spinlock_unlock(&hw->phy_lock);
163 
164 			goto skip_an;
165 		}
166 
167 		rte_spinlock_lock(&hw->phy_lock);
168 		/*disable 100/10base-T Self-negotiation ability*/
169 		ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
170 		value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
171 			YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
172 		ngbe_write_phy_reg_mdi(hw, YT_ANA, 0, value);
173 
174 		/*disable 1000base-T Self-negotiation ability*/
175 		ngbe_read_phy_reg_mdi(hw, YT_MS_CTRL, 0, &value);
176 		value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
177 		ngbe_write_phy_reg_mdi(hw, YT_MS_CTRL, 0, value);
178 
179 		if (speed & NGBE_LINK_SPEED_1GB_FULL) {
180 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
181 			value_r9 |= YT_MS_1000BASET_FULL;
182 		}
183 		if (speed & NGBE_LINK_SPEED_100M_FULL) {
184 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
185 			value_r4 |= YT_ANA_100BASET_FULL;
186 		}
187 		if (speed & NGBE_LINK_SPEED_10M_FULL) {
188 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
189 			value_r4 |= YT_ANA_10BASET_FULL;
190 		}
191 
192 		/* enable 1000base-T Self-negotiation ability */
193 		ngbe_read_phy_reg_mdi(hw, YT_MS_CTRL, 0, &value);
194 		value |= value_r9;
195 		ngbe_write_phy_reg_mdi(hw, YT_MS_CTRL, 0, value);
196 
197 		/* enable 100/10base-T Self-negotiation ability */
198 		ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
199 		value |= value_r4;
200 		ngbe_write_phy_reg_mdi(hw, YT_ANA, 0, value);
201 
202 		/* software reset to make the above configuration take effect*/
203 		ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
204 		value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
205 		ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
206 		rte_spinlock_unlock(&hw->phy_lock);
207 skip_an:
208 		hw->phy.set_phy_power(hw, true);
209 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1)) {
210 		/* fiber to rgmii */
211 		if (!hw->mac.autoneg) {
212 			switch (speed) {
213 			case NGBE_LINK_SPEED_1GB_FULL:
214 				value = NGBE_LINK_SPEED_1GB_FULL;
215 				break;
216 			case NGBE_LINK_SPEED_100M_FULL:
217 				value = NGBE_LINK_SPEED_100M_FULL;
218 				break;
219 			default:
220 				value = NGBE_LINK_SPEED_1GB_FULL;
221 				break;
222 			}
223 			hw->phy.autoneg_advertised |= value;
224 			goto skip_an_fiber;
225 		}
226 
227 		value = 0;
228 		if (speed & NGBE_LINK_SPEED_1GB_FULL)
229 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
230 		if (speed & NGBE_LINK_SPEED_100M_FULL)
231 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
232 
233 skip_an_fiber:
234 		rte_spinlock_lock(&hw->phy_lock);
235 		ngbe_read_phy_reg_ext_yt(hw, YT_MISC, 0, &value);
236 		if (hw->phy.autoneg_advertised & NGBE_LINK_SPEED_1GB_FULL)
237 			value |= YT_MISC_RESV;
238 		else if (hw->phy.autoneg_advertised & NGBE_LINK_SPEED_100M_FULL)
239 			value &= ~YT_MISC_RESV;
240 		ngbe_write_phy_reg_ext_yt(hw, YT_MISC, 0, value);
241 
242 		/* close auto sensing */
243 		ngbe_read_phy_reg_sds_ext_yt(hw, YT_AUTO, 0, &value);
244 		value &= ~YT_AUTO_SENSING;
245 		ngbe_write_phy_reg_sds_ext_yt(hw, YT_AUTO, 0, value);
246 
247 		ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
248 		value &= ~YT_CHIP_SW_RST;
249 		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
250 
251 		/* RGMII_Config1 : Config rx and tx training delay */
252 		value = YT_RGMII_CONF1_RXDELAY |
253 			YT_RGMII_CONF1_TXDELAY_FE |
254 			YT_RGMII_CONF1_TXDELAY;
255 
256 		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
257 		value = YT_CHIP_MODE_SEL(1) |
258 			YT_CHIP_SW_LDO_EN |
259 			YT_CHIP_SW_RST;
260 		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
261 
262 		/* software reset */
263 		if (hw->mac.autoneg) {
264 			value = YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN |
265 				YT_BCR_DUPLEX | YT_BCR_SPEED_SELECT1;
266 		} else {
267 			value = YT_BCR_RESET | YT_BCR_DUPLEX;
268 			if (speed & NGBE_LINK_SPEED_1GB_FULL)
269 				value |= YT_BCR_SPEED_SELECT1;
270 			if (speed & NGBE_LINK_SPEED_100M_FULL)
271 				value |= YT_BCR_SPEED_SELECT0;
272 		}
273 		hw->phy.write_reg(hw, YT_BCR, 0, value);
274 		rte_spinlock_unlock(&hw->phy_lock);
275 
276 		hw->phy.set_phy_power(hw, true);
277 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(2)) {
278 		hw->phy.set_phy_power(hw, true);
279 
280 		rte_spinlock_lock(&hw->phy_lock);
281 		hw->phy.read_reg(hw, YT_SPST, 0, &value);
282 		rte_spinlock_unlock(&hw->phy_lock);
283 		if (value & YT_SPST_LINK) {
284 			/* fiber up */
285 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
286 		} else {
287 			/* utp up */
288 			rte_spinlock_lock(&hw->phy_lock);
289 			/*disable 100/10base-T Self-negotiation ability*/
290 			ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
291 			value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
292 				YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
293 			ngbe_write_phy_reg_mdi(hw, YT_ANA, 0, value);
294 
295 			/*disable 1000base-T Self-negotiation ability*/
296 			ngbe_read_phy_reg_mdi(hw, YT_MS_CTRL, 0, &value);
297 			value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
298 			ngbe_write_phy_reg_mdi(hw, YT_MS_CTRL, 0, value);
299 
300 			if (speed & NGBE_LINK_SPEED_1GB_FULL) {
301 				hw->phy.autoneg_advertised |=
302 						NGBE_LINK_SPEED_1GB_FULL;
303 				value_r9 |= YT_MS_1000BASET_FULL;
304 			}
305 			if (speed & NGBE_LINK_SPEED_100M_FULL) {
306 				hw->phy.autoneg_advertised |=
307 						NGBE_LINK_SPEED_100M_FULL;
308 				value_r4 |= YT_ANA_100BASET_FULL;
309 			}
310 			if (speed & NGBE_LINK_SPEED_10M_FULL) {
311 				hw->phy.autoneg_advertised |=
312 						NGBE_LINK_SPEED_10M_FULL;
313 				value_r4 |= YT_ANA_10BASET_FULL;
314 			}
315 
316 			/* enable 1000base-T Self-negotiation ability */
317 			ngbe_read_phy_reg_mdi(hw, YT_MS_CTRL, 0, &value);
318 			value |= value_r9;
319 			ngbe_write_phy_reg_mdi(hw, YT_MS_CTRL, 0, value);
320 
321 			/* enable 100/10base-T Self-negotiation ability */
322 			ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
323 			value |= value_r4;
324 			ngbe_write_phy_reg_mdi(hw, YT_ANA, 0, value);
325 
326 			/* config for yt8531sh-ca */
327 			ngbe_write_phy_reg_ext_yt(hw, YT_SPEC_CONF, 0,
328 						YT_SPEC_CONF_8531SH_CA);
329 
330 			/* software reset to make the above configuration
331 			 * take effect
332 			 */
333 			ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
334 			value |= YT_BCR_RESET;
335 			ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
336 			rte_spinlock_unlock(&hw->phy_lock);
337 		}
338 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(4)) {
339 		hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
340 
341 		rte_spinlock_lock(&hw->phy_lock);
342 		ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, &value);
343 		value |= YT_RGMII_CONF1_MODE;
344 		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
345 
346 		ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, &value);
347 		value &= ~(YT_RGMII_CONF2_SPEED_MASK | YT_RGMII_CONF2_DUPLEX |
348 			YT_RGMII_CONF2_LINKUP);
349 		value |= YT_RGMII_CONF2_SPEED(2) | YT_RGMII_CONF2_DUPLEX |
350 			YT_RGMII_CONF2_LINKUP;
351 		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, value);
352 
353 		ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
354 		value &= ~YT_SMI_PHY_SW_RST;
355 		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
356 		rte_spinlock_unlock(&hw->phy_lock);
357 
358 		hw->phy.set_phy_power(hw, true);
359 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(5)) {
360 		/* sgmii_to_rgmii */
361 		if (!hw->mac.autoneg) {
362 			switch (speed) {
363 			case NGBE_LINK_SPEED_1GB_FULL:
364 				value = YT_BCR_SPEED_SELECT1;
365 				break;
366 			case NGBE_LINK_SPEED_100M_FULL:
367 				value = YT_BCR_SPEED_SELECT0;
368 				break;
369 			case NGBE_LINK_SPEED_10M_FULL:
370 				value = 0;
371 				break;
372 			default:
373 				value = YT_BCR_SPEED_SELECT0 |
374 					YT_BCR_SPEED_SELECT1;
375 				DEBUGOUT("unknown speed = 0x%x", speed);
376 				break;
377 			}
378 			/* duplex full */
379 			value |= YT_BCR_DUPLEX | YT_BCR_RESET;
380 			rte_spinlock_lock(&hw->phy_lock);
381 			hw->phy.write_reg(hw, YT_BCR, 0, value);
382 			rte_spinlock_unlock(&hw->phy_lock);
383 
384 			goto skip_an_sr;
385 		}
386 
387 		value = 0;
388 		if (speed & NGBE_LINK_SPEED_1GB_FULL) {
389 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
390 			value |= YT_BCR_SPEED_SELECT1;
391 		}
392 		if (speed & NGBE_LINK_SPEED_100M_FULL) {
393 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
394 			value |= YT_BCR_SPEED_SELECT0;
395 		}
396 		if (speed & NGBE_LINK_SPEED_10M_FULL)
397 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
398 
399 		/* duplex full */
400 		value |= YT_BCR_DUPLEX | YT_BCR_RESET;
401 		rte_spinlock_lock(&hw->phy_lock);
402 		hw->phy.write_reg(hw, YT_BCR, 0, value);
403 
404 		/* software reset to make the above configuration take effect */
405 		hw->phy.read_reg(hw, YT_BCR, 0, &value);
406 		value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
407 		hw->phy.write_reg(hw, 0x0, 0, value);
408 		rte_spinlock_unlock(&hw->phy_lock);
409 
410 skip_an_sr:
411 		hw->phy.set_phy_power(hw, true);
412 	}
413 
414 	rte_spinlock_lock(&hw->phy_lock);
415 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
416 	ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
417 	rte_spinlock_unlock(&hw->phy_lock);
418 
419 	return 0;
420 }
421 
ngbe_reset_phy_yt(struct ngbe_hw * hw)422 s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
423 {
424 	u32 i;
425 	u16 ctrl = 0;
426 	s32 status = 0;
427 
428 	if (hw->phy.type != ngbe_phy_yt8521s &&
429 		hw->phy.type != ngbe_phy_yt8521s_sfi)
430 		return NGBE_ERR_PHY_TYPE;
431 
432 	rte_spinlock_lock(&hw->phy_lock);
433 	/* check chip_mode first */
434 	ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &ctrl);
435 	if (ctrl & YT_CHIP_MODE_MASK) {
436 		/* fiber to rgmii */
437 		status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
438 		/* sds software reset */
439 		ctrl |= YT_BCR_RESET;
440 		status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
441 
442 		for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
443 			status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
444 			if (!(ctrl & YT_BCR_RESET))
445 				break;
446 			msleep(1);
447 		}
448 	} else {
449 		/* UTP to rgmii */
450 		status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
451 		/* sds software reset */
452 		ctrl |= YT_BCR_RESET;
453 		status = ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, ctrl);
454 
455 		for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
456 			status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
457 			if (!(ctrl & YT_BCR_RESET))
458 				break;
459 			msleep(1);
460 		}
461 	}
462 	rte_spinlock_unlock(&hw->phy_lock);
463 
464 	if (i == YT_PHY_RST_WAIT_PERIOD) {
465 		DEBUGOUT("PHY reset polling failed to complete.");
466 		return NGBE_ERR_RESET_FAILED;
467 	}
468 
469 	return status;
470 }
471 
ngbe_get_phy_advertised_pause_yt(struct ngbe_hw * hw,u8 * pause_bit)472 s32 ngbe_get_phy_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
473 {
474 	u16 value;
475 	s32 status = 0;
476 
477 	rte_spinlock_lock(&hw->phy_lock);
478 	status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
479 	rte_spinlock_unlock(&hw->phy_lock);
480 	value &= YT_FANA_PAUSE_MASK;
481 	*pause_bit = (u8)(value >> 7);
482 
483 	return status;
484 }
485 
ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw * hw,u8 * pause_bit)486 s32 ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
487 {
488 	u16 value;
489 	s32 status = 0;
490 
491 	rte_spinlock_lock(&hw->phy_lock);
492 	status = hw->phy.read_reg(hw, YT_LPAR, 0, &value);
493 	rte_spinlock_unlock(&hw->phy_lock);
494 	value &= YT_FLPAR_PAUSE_MASK;
495 	*pause_bit = (u8)(value >> 7);
496 
497 	return status;
498 }
499 
ngbe_set_phy_pause_adv_yt(struct ngbe_hw * hw,u16 pause_bit)500 s32 ngbe_set_phy_pause_adv_yt(struct ngbe_hw *hw, u16 pause_bit)
501 {
502 	u16 value;
503 	s32 status = 0;
504 
505 	rte_spinlock_lock(&hw->phy_lock);
506 	status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
507 	value &= ~YT_FANA_PAUSE_MASK;
508 	value |= pause_bit;
509 	status = hw->phy.write_reg(hw, YT_ANA, 0, value);
510 	rte_spinlock_unlock(&hw->phy_lock);
511 
512 	return status;
513 }
514 
ngbe_check_phy_link_yt(struct ngbe_hw * hw,u32 * speed,bool * link_up)515 s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
516 		u32 *speed, bool *link_up)
517 {
518 	s32 status = 0;
519 	u16 phy_link = 0;
520 	u16 phy_speed = 0;
521 	u16 phy_data = 0;
522 	u16 insr = 0;
523 
524 	/* Initialize speed and link to default case */
525 	*link_up = false;
526 	*speed = NGBE_LINK_SPEED_UNKNOWN;
527 	rte_spinlock_lock(&hw->phy_lock);
528 
529 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
530 	ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
531 
532 	status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data);
533 	phy_link = phy_data & YT_SPST_LINK;
534 	phy_speed = phy_data & YT_SPST_SPEED_MASK;
535 
536 	if (phy_link) {
537 		*link_up = true;
538 	} else {
539 		status = ngbe_read_phy_reg_mdi(hw, YT_SPST, 0, &phy_data);
540 		phy_link = phy_data & YT_SPST_LINK;
541 		phy_speed = phy_data & YT_SPST_SPEED_MASK;
542 
543 		if (phy_link)
544 			*link_up = true;
545 	}
546 
547 	rte_spinlock_unlock(&hw->phy_lock);
548 	if (*link_up) {
549 		if (phy_speed == YT_SPST_SPEED_1000M)
550 			*speed = NGBE_LINK_SPEED_1GB_FULL;
551 		else if (phy_speed == YT_SPST_SPEED_100M)
552 			*speed = NGBE_LINK_SPEED_100M_FULL;
553 		else if (phy_speed == YT_SPST_SPEED_10M)
554 			*speed = NGBE_LINK_SPEED_10M_FULL;
555 	}
556 
557 	return status;
558 }
559 
ngbe_set_phy_power_yt(struct ngbe_hw * hw,bool on)560 s32 ngbe_set_phy_power_yt(struct ngbe_hw *hw, bool on)
561 {
562 	u16 value = 0;
563 
564 	rte_spinlock_lock(&hw->phy_lock);
565 	/* power down/up in fiber mode */
566 	hw->phy.read_reg(hw, YT_BCR, 0, &value);
567 	if (on)
568 		value &= ~YT_BCR_PWDN;
569 	else
570 		value |= YT_BCR_PWDN;
571 	hw->phy.write_reg(hw, YT_BCR, 0, value);
572 
573 	value = 0;
574 	/* power down/up in UTP mode */
575 	ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
576 	if (on)
577 		value &= ~YT_BCR_PWDN;
578 	else
579 		value |= YT_BCR_PWDN;
580 	ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
581 	rte_spinlock_unlock(&hw->phy_lock);
582 
583 	return 0;
584 }
585