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(®, ®22);
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(®, ®22);
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