xref: /dpdk/drivers/net/ngbe/base/ngbe_phy_yt.c (revision c811e6a4)
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 	u16 value = 0;
104 
105 	/* close sds area register */
106 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
107 	/* enable interrupts */
108 	ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
109 				YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
110 
111 	/* power down in fiber mode */
112 	hw->phy.read_reg(hw, YT_BCR, 0, &value);
113 	value |= YT_BCR_PWDN;
114 	hw->phy.write_reg(hw, YT_BCR, 0, value);
115 
116 	/* power down in UTP mode */
117 	ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
118 	value |= YT_BCR_PWDN;
119 	ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
120 
121 	return 0;
122 }
123 
ngbe_setup_phy_link_yt(struct ngbe_hw * hw,u32 speed,bool autoneg_wait_to_complete)124 s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
125 				bool autoneg_wait_to_complete)
126 {
127 	u16 value_r4 = 0;
128 	u16 value_r9 = 0;
129 	u16 value;
130 
131 	UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
132 
133 	hw->phy.autoneg_advertised = 0;
134 
135 	/* check chip_mode first */
136 	ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
137 	if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(0)) {
138 		/* UTP to rgmii */
139 		if (!hw->mac.autoneg) {
140 			switch (speed) {
141 			case NGBE_LINK_SPEED_1GB_FULL:
142 				value = YT_BCR_SPEED_SELECT1;
143 				break;
144 			case NGBE_LINK_SPEED_100M_FULL:
145 				value = YT_BCR_SPEED_SELECT0;
146 				break;
147 			case NGBE_LINK_SPEED_10M_FULL:
148 				value = 0;
149 				break;
150 			default:
151 				value = YT_BCR_SPEED_SELECT0 |
152 					YT_BCR_SPEED_SELECT1;
153 				DEBUGOUT("unknown speed = 0x%x.",
154 					speed);
155 				break;
156 			}
157 			/* duplex full */
158 			value |= YT_BCR_DUPLEX | YT_BCR_RESET;
159 			hw->phy.write_reg(hw, YT_BCR, 0, value);
160 
161 			goto skip_an;
162 		}
163 
164 		/*disable 100/10base-T Self-negotiation ability*/
165 		hw->phy.read_reg(hw, YT_ANA, 0, &value);
166 		value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
167 			YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
168 		hw->phy.write_reg(hw, YT_ANA, 0, value);
169 
170 		/*disable 1000base-T Self-negotiation ability*/
171 		hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
172 		value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
173 		hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
174 
175 		if (speed & NGBE_LINK_SPEED_1GB_FULL) {
176 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
177 			value_r9 |= YT_MS_1000BASET_FULL;
178 		}
179 		if (speed & NGBE_LINK_SPEED_100M_FULL) {
180 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
181 			value_r4 |= YT_ANA_100BASET_FULL;
182 		}
183 		if (speed & NGBE_LINK_SPEED_10M_FULL) {
184 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
185 			value_r4 |= YT_ANA_10BASET_FULL;
186 		}
187 
188 		/* enable 1000base-T Self-negotiation ability */
189 		hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
190 		value |= value_r9;
191 		hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
192 
193 		/* enable 100/10base-T Self-negotiation ability */
194 		hw->phy.read_reg(hw, YT_ANA, 0, &value);
195 		value |= value_r4;
196 		hw->phy.write_reg(hw, YT_ANA, 0, value);
197 
198 		/* software reset to make the above configuration take effect*/
199 		hw->phy.read_reg(hw, YT_BCR, 0, &value);
200 		value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
201 		hw->phy.write_reg(hw, YT_BCR, 0, value);
202 skip_an:
203 		/* power on in UTP mode */
204 		ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
205 		value &= ~YT_BCR_PWDN;
206 		ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
207 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1)) {
208 		/* fiber to rgmii */
209 		hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
210 
211 		/* RGMII_Config1 : Config rx and tx training delay */
212 		value = YT_RGMII_CONF1_RXDELAY |
213 			YT_RGMII_CONF1_TXDELAY_FE |
214 			YT_RGMII_CONF1_TXDELAY;
215 		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
216 		value = YT_CHIP_MODE_SEL(1) |
217 			YT_CHIP_SW_LDO_EN |
218 			YT_CHIP_SW_RST;
219 		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
220 
221 		/* software reset */
222 		ngbe_write_phy_reg_sds_ext_yt(hw, 0x0, 0, 0x9140);
223 
224 		/* power on phy */
225 		hw->phy.read_reg(hw, YT_BCR, 0, &value);
226 		value &= ~YT_BCR_PWDN;
227 		hw->phy.write_reg(hw, YT_BCR, 0, value);
228 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(2)) {
229 		/* power on in UTP mode */
230 		ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
231 		value &= ~YT_BCR_PWDN;
232 		ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
233 		/* power down in fiber mode */
234 		hw->phy.read_reg(hw, YT_BCR, 0, &value);
235 		value &= ~YT_BCR_PWDN;
236 		hw->phy.write_reg(hw, YT_BCR, 0, value);
237 
238 		hw->phy.read_reg(hw, YT_SPST, 0, &value);
239 		if (value & YT_SPST_LINK) {
240 			/* fiber up */
241 			hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
242 		} else {
243 			/* utp up */
244 			/*disable 100/10base-T Self-negotiation ability*/
245 			hw->phy.read_reg(hw, YT_ANA, 0, &value);
246 			value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
247 				YT_ANA_10BASET_FULL | YT_ANA_10BASET_HALF);
248 			hw->phy.write_reg(hw, YT_ANA, 0, value);
249 
250 			/*disable 1000base-T Self-negotiation ability*/
251 			hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
252 			value &= ~(YT_MS_1000BASET_FULL | YT_MS_1000BASET_HALF);
253 			hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
254 
255 			if (speed & NGBE_LINK_SPEED_1GB_FULL) {
256 				hw->phy.autoneg_advertised |=
257 						NGBE_LINK_SPEED_1GB_FULL;
258 				value_r9 |= YT_MS_1000BASET_FULL;
259 			}
260 			if (speed & NGBE_LINK_SPEED_100M_FULL) {
261 				hw->phy.autoneg_advertised |=
262 						NGBE_LINK_SPEED_100M_FULL;
263 				value_r4 |= YT_ANA_100BASET_FULL;
264 			}
265 			if (speed & NGBE_LINK_SPEED_10M_FULL) {
266 				hw->phy.autoneg_advertised |=
267 						NGBE_LINK_SPEED_10M_FULL;
268 				value_r4 |= YT_ANA_10BASET_FULL;
269 			}
270 
271 			/* enable 1000base-T Self-negotiation ability */
272 			hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
273 			value |= value_r9;
274 			hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
275 
276 			/* enable 100/10base-T Self-negotiation ability */
277 			hw->phy.read_reg(hw, YT_ANA, 0, &value);
278 			value |= value_r4;
279 			hw->phy.write_reg(hw, YT_ANA, 0, value);
280 
281 			/* software reset to make the above configuration
282 			 * take effect
283 			 */
284 			hw->phy.read_reg(hw, YT_BCR, 0, &value);
285 			value |= YT_BCR_RESET;
286 			hw->phy.write_reg(hw, YT_BCR, 0, value);
287 		}
288 	} else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(4)) {
289 		hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
290 
291 		ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, &value);
292 		value |= YT_RGMII_CONF1_MODE;
293 		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
294 
295 		ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, &value);
296 		value &= ~(YT_RGMII_CONF2_SPEED_MASK | YT_RGMII_CONF2_DUPLEX |
297 			YT_RGMII_CONF2_LINKUP);
298 		value |= YT_RGMII_CONF2_SPEED(2) | YT_RGMII_CONF2_DUPLEX |
299 			YT_RGMII_CONF2_LINKUP;
300 		ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF2, 0, value);
301 
302 		ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
303 		value &= ~YT_SMI_PHY_SW_RST;
304 		ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
305 
306 		/* power on phy */
307 		hw->phy.read_reg(hw, YT_BCR, 0, &value);
308 		value &= ~YT_BCR_PWDN;
309 		hw->phy.write_reg(hw, YT_BCR, 0, value);
310 	}
311 
312 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
313 	ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
314 
315 	return 0;
316 }
317 
ngbe_reset_phy_yt(struct ngbe_hw * hw)318 s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
319 {
320 	u32 i;
321 	u16 ctrl = 0;
322 	s32 status = 0;
323 
324 	if (hw->phy.type != ngbe_phy_yt8521s &&
325 		hw->phy.type != ngbe_phy_yt8521s_sfi)
326 		return NGBE_ERR_PHY_TYPE;
327 
328 	/* check chip_mode first */
329 	ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &ctrl);
330 	if (ctrl & YT_CHIP_MODE_MASK) {
331 		/* fiber to rgmii */
332 		status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
333 		/* sds software reset */
334 		ctrl |= YT_BCR_RESET;
335 		status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
336 
337 		for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
338 			status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
339 			if (!(ctrl & YT_BCR_RESET))
340 				break;
341 			msleep(1);
342 		}
343 	} else {
344 		/* UTP to rgmii */
345 		status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
346 		/* sds software reset */
347 		ctrl |= YT_BCR_RESET;
348 		status = ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, ctrl);
349 
350 		for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
351 			status = ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &ctrl);
352 			if (!(ctrl & YT_BCR_RESET))
353 				break;
354 			msleep(1);
355 		}
356 	}
357 
358 	if (i == YT_PHY_RST_WAIT_PERIOD) {
359 		DEBUGOUT("PHY reset polling failed to complete.");
360 		return NGBE_ERR_RESET_FAILED;
361 	}
362 
363 	return status;
364 }
365 
ngbe_get_phy_advertised_pause_yt(struct ngbe_hw * hw,u8 * pause_bit)366 s32 ngbe_get_phy_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
367 {
368 	u16 value;
369 	s32 status = 0;
370 
371 	status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
372 	value &= YT_FANA_PAUSE_MASK;
373 	*pause_bit = (u8)(value >> 7);
374 
375 	return status;
376 }
377 
ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw * hw,u8 * pause_bit)378 s32 ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw *hw, u8 *pause_bit)
379 {
380 	u16 value;
381 	s32 status = 0;
382 
383 	status = hw->phy.read_reg(hw, YT_LPAR, 0, &value);
384 	value &= YT_FLPAR_PAUSE_MASK;
385 	*pause_bit = (u8)(value >> 7);
386 
387 	return status;
388 }
389 
ngbe_set_phy_pause_adv_yt(struct ngbe_hw * hw,u16 pause_bit)390 s32 ngbe_set_phy_pause_adv_yt(struct ngbe_hw *hw, u16 pause_bit)
391 {
392 	u16 value;
393 	s32 status = 0;
394 
395 	status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
396 	value &= ~YT_FANA_PAUSE_MASK;
397 	value |= pause_bit;
398 	status = hw->phy.write_reg(hw, YT_ANA, 0, value);
399 
400 	return status;
401 }
402 
ngbe_check_phy_link_yt(struct ngbe_hw * hw,u32 * speed,bool * link_up)403 s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
404 		u32 *speed, bool *link_up)
405 {
406 	s32 status = 0;
407 	u16 phy_link = 0;
408 	u16 phy_speed = 0;
409 	u16 phy_data = 0;
410 	u16 insr = 0;
411 
412 	/* Initialize speed and link to default case */
413 	*link_up = false;
414 	*speed = NGBE_LINK_SPEED_UNKNOWN;
415 
416 	ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
417 	ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
418 
419 	status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data);
420 	phy_link = phy_data & YT_SPST_LINK;
421 	phy_speed = phy_data & YT_SPST_SPEED_MASK;
422 
423 	if (phy_link) {
424 		*link_up = true;
425 
426 		if (phy_speed == YT_SPST_SPEED_1000M)
427 			*speed = NGBE_LINK_SPEED_1GB_FULL;
428 		else if (phy_speed == YT_SPST_SPEED_100M)
429 			*speed = NGBE_LINK_SPEED_100M_FULL;
430 		else if (phy_speed == YT_SPST_SPEED_10M)
431 			*speed = NGBE_LINK_SPEED_10M_FULL;
432 	}
433 
434 	return status;
435 }
436 
437