xref: /dpdk/drivers/net/ngbe/base/ngbe_phy.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5 
6 #include "ngbe_hw.h"
7 #include "ngbe_phy.h"
8 
9 s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22)
10 {
11 	bool match = 1;
12 	switch (reg->device_type) {
13 	case NGBE_MD_DEV_PMA_PMD:
14 		switch (reg->addr) {
15 		case NGBE_MD_PHY_ID_HIGH:
16 		case NGBE_MD_PHY_ID_LOW:
17 			reg22->page = 0;
18 			reg22->addr = reg->addr;
19 			reg22->device_type = 0;
20 			break;
21 		default:
22 			match = 0;
23 		}
24 		break;
25 	default:
26 		match = 0;
27 		break;
28 	}
29 
30 	if (!match) {
31 		reg22->page = reg->device_type;
32 		reg22->device_type = reg->device_type;
33 		reg22->addr = reg->addr;
34 	}
35 
36 	return 0;
37 }
38 
39 /**
40  * ngbe_probe_phy - Identify a single address for a PHY
41  * @hw: pointer to hardware structure
42  * @phy_addr: PHY address to probe
43  *
44  * Returns true if PHY found
45  */
46 static bool ngbe_probe_phy(struct ngbe_hw *hw, u16 phy_addr)
47 {
48 	if (!ngbe_validate_phy_addr(hw, phy_addr)) {
49 		DEBUGOUT("Unable to validate PHY address 0x%04X\n",
50 			phy_addr);
51 		return false;
52 	}
53 
54 	if (ngbe_get_phy_id(hw))
55 		return false;
56 
57 	hw->phy.type = ngbe_get_phy_type_from_id(hw);
58 	if (hw->phy.type == ngbe_phy_unknown)
59 		return false;
60 
61 	return true;
62 }
63 
64 /**
65  *  ngbe_identify_phy - Get physical layer module
66  *  @hw: pointer to hardware structure
67  *
68  *  Determines the physical layer module found on the current adapter.
69  **/
70 s32 ngbe_identify_phy(struct ngbe_hw *hw)
71 {
72 	s32 err = NGBE_ERR_PHY_ADDR_INVALID;
73 	u16 phy_addr;
74 
75 	DEBUGFUNC("ngbe_identify_phy");
76 
77 	if (hw->phy.type != ngbe_phy_unknown)
78 		return 0;
79 
80 	/* select clause22 */
81 	wr32(hw, NGBE_MDIOMODE, NGBE_MDIOMODE_MASK);
82 
83 	for (phy_addr = 0; phy_addr < NGBE_MAX_PHY_ADDR; phy_addr++) {
84 		if (ngbe_probe_phy(hw, phy_addr)) {
85 			err = 0;
86 			break;
87 		}
88 	}
89 
90 	return err;
91 }
92 
93 /**
94  * ngbe_check_reset_blocked - check status of MNG FW veto bit
95  * @hw: pointer to the hardware structure
96  *
97  * This function checks the STAT.MNGVETO bit to see if there are
98  * any constraints on link from manageability.  For MAC's that don't
99  * have this bit just return faluse since the link can not be blocked
100  * via this method.
101  **/
102 s32 ngbe_check_reset_blocked(struct ngbe_hw *hw)
103 {
104 	u32 mmngc;
105 
106 	DEBUGFUNC("ngbe_check_reset_blocked");
107 
108 	mmngc = rd32(hw, NGBE_STAT);
109 	if (mmngc & NGBE_STAT_MNGVETO) {
110 		DEBUGOUT("MNG_VETO bit detected.\n");
111 		return true;
112 	}
113 
114 	return false;
115 }
116 
117 /**
118  *  ngbe_validate_phy_addr - Determines phy address is valid
119  *  @hw: pointer to hardware structure
120  *  @phy_addr: PHY address
121  *
122  **/
123 bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr)
124 {
125 	u16 phy_id = 0;
126 	bool valid = false;
127 
128 	DEBUGFUNC("ngbe_validate_phy_addr");
129 
130 	if (hw->sub_device_id == NGBE_SUB_DEV_ID_EM_YT8521S_SFP)
131 		return true;
132 
133 	hw->phy.addr = phy_addr;
134 	hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH,
135 			     NGBE_MD_DEV_PMA_PMD, &phy_id);
136 
137 	if (phy_id != 0xFFFF && phy_id != 0x0)
138 		valid = true;
139 
140 	DEBUGOUT("PHY ID HIGH is 0x%04X\n", phy_id);
141 
142 	return valid;
143 }
144 
145 /**
146  *  ngbe_get_phy_id - Get the phy ID
147  *  @hw: pointer to hardware structure
148  *
149  **/
150 s32 ngbe_get_phy_id(struct ngbe_hw *hw)
151 {
152 	u32 err;
153 	u16 phy_id_high = 0;
154 	u16 phy_id_low = 0;
155 
156 	DEBUGFUNC("ngbe_get_phy_id");
157 
158 	err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH,
159 				      NGBE_MD_DEV_PMA_PMD,
160 				      &phy_id_high);
161 	hw->phy.id = (u32)(phy_id_high << 16);
162 
163 	err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW,
164 				NGBE_MD_DEV_PMA_PMD,
165 				&phy_id_low);
166 	hw->phy.id |= (u32)(phy_id_low & NGBE_PHY_REVISION_MASK);
167 	hw->phy.revision = (u32)(phy_id_low & ~NGBE_PHY_REVISION_MASK);
168 
169 	DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X\n",
170 		  phy_id_high, phy_id_low);
171 
172 	return err;
173 }
174 
175 /**
176  *  ngbe_get_phy_type_from_id - Get the phy type
177  *  @phy_id: PHY ID information
178  *
179  **/
180 enum ngbe_phy_type ngbe_get_phy_type_from_id(struct ngbe_hw *hw)
181 {
182 	enum ngbe_phy_type phy_type;
183 
184 	DEBUGFUNC("ngbe_get_phy_type_from_id");
185 
186 	switch (hw->phy.id) {
187 	case NGBE_PHYID_RTL:
188 		phy_type = ngbe_phy_rtl;
189 		break;
190 	case NGBE_PHYID_MVL:
191 		if (hw->phy.media_type == ngbe_media_type_fiber)
192 			phy_type = ngbe_phy_mvl_sfi;
193 		else
194 			phy_type = ngbe_phy_mvl;
195 		break;
196 	case NGBE_PHYID_YT:
197 		if (hw->phy.media_type == ngbe_media_type_fiber)
198 			phy_type = ngbe_phy_yt8521s_sfi;
199 		else
200 			phy_type = ngbe_phy_yt8521s;
201 		break;
202 	default:
203 		phy_type = ngbe_phy_unknown;
204 		break;
205 	}
206 
207 	return phy_type;
208 }
209 
210 /**
211  *  ngbe_reset_phy - Performs a PHY reset
212  *  @hw: pointer to hardware structure
213  **/
214 s32 ngbe_reset_phy(struct ngbe_hw *hw)
215 {
216 	s32 err = 0;
217 
218 	DEBUGFUNC("ngbe_reset_phy");
219 
220 	if (hw->phy.type == ngbe_phy_unknown)
221 		err = ngbe_identify_phy(hw);
222 
223 	if (err != 0 || hw->phy.type == ngbe_phy_none)
224 		return err;
225 
226 	/* Don't reset PHY if it's shut down due to overtemp. */
227 	if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP)
228 		return err;
229 
230 	/* Blocked by MNG FW so bail */
231 	if (ngbe_check_reset_blocked(hw))
232 		return err;
233 
234 	switch (hw->phy.type) {
235 	case ngbe_phy_rtl:
236 		err = ngbe_reset_phy_rtl(hw);
237 		break;
238 	case ngbe_phy_mvl:
239 	case ngbe_phy_mvl_sfi:
240 		err = ngbe_reset_phy_mvl(hw);
241 		break;
242 	case ngbe_phy_yt8521s:
243 	case ngbe_phy_yt8521s_sfi:
244 		err = ngbe_reset_phy_yt(hw);
245 		break;
246 	default:
247 		break;
248 	}
249 
250 	return err;
251 }
252 
253 /**
254  *  ngbe_read_phy_mdi - Reads a value from a specified PHY register without
255  *  the SWFW lock
256  *  @hw: pointer to hardware structure
257  *  @reg_addr: 32 bit address of PHY register to read
258  *  @device_type: 5 bit device type
259  *  @phy_data: Pointer to read data from PHY register
260  **/
261 s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type,
262 			   u16 *phy_data)
263 {
264 	u32 command, data;
265 
266 	/* Setup and write the address cycle command */
267 	command = NGBE_MDIOSCA_REG(reg_addr) |
268 		  NGBE_MDIOSCA_DEV(device_type) |
269 		  NGBE_MDIOSCA_PORT(hw->phy.addr);
270 	wr32(hw, NGBE_MDIOSCA, command);
271 
272 	command = NGBE_MDIOSCD_CMD_READ |
273 		  NGBE_MDIOSCD_BUSY |
274 		  NGBE_MDIOSCD_CLOCK(6);
275 	wr32(hw, NGBE_MDIOSCD, command);
276 
277 	/*
278 	 * Check every 10 usec to see if the address cycle completed.
279 	 * The MDI Command bit will clear when the operation is
280 	 * complete
281 	 */
282 	if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY,
283 		0, NULL, 100, 100)) {
284 		DEBUGOUT("PHY address command did not complete\n");
285 		return NGBE_ERR_PHY;
286 	}
287 
288 	data = rd32(hw, NGBE_MDIOSCD);
289 	*phy_data = (u16)NGBE_MDIOSCD_DAT_R(data);
290 
291 	return 0;
292 }
293 
294 /**
295  *  ngbe_read_phy_reg - Reads a value from a specified PHY register
296  *  using the SWFW lock - this function is needed in most cases
297  *  @hw: pointer to hardware structure
298  *  @reg_addr: 32 bit address of PHY register to read
299  *  @device_type: 5 bit device type
300  *  @phy_data: Pointer to read data from PHY register
301  **/
302 s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
303 			       u32 device_type, u16 *phy_data)
304 {
305 	s32 err;
306 	u32 gssr = hw->phy.phy_semaphore_mask;
307 
308 	DEBUGFUNC("ngbe_read_phy_reg");
309 
310 	if (hw->mac.acquire_swfw_sync(hw, gssr))
311 		return NGBE_ERR_SWFW_SYNC;
312 
313 	err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type,
314 					phy_data);
315 
316 	hw->mac.release_swfw_sync(hw, gssr);
317 
318 	return err;
319 }
320 
321 /**
322  *  ngbe_write_phy_reg_mdi - Writes a value to specified PHY register
323  *  without SWFW lock
324  *  @hw: pointer to hardware structure
325  *  @reg_addr: 32 bit PHY register to write
326  *  @device_type: 5 bit device type
327  *  @phy_data: Data to write to the PHY register
328  **/
329 s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr,
330 				u32 device_type, u16 phy_data)
331 {
332 	u32 command;
333 
334 	/* write command */
335 	command = NGBE_MDIOSCA_REG(reg_addr) |
336 		  NGBE_MDIOSCA_DEV(device_type) |
337 		  NGBE_MDIOSCA_PORT(hw->phy.addr);
338 	wr32(hw, NGBE_MDIOSCA, command);
339 
340 	command = NGBE_MDIOSCD_CMD_WRITE |
341 		  NGBE_MDIOSCD_DAT(phy_data) |
342 		  NGBE_MDIOSCD_BUSY |
343 		  NGBE_MDIOSCD_CLOCK(6);
344 	wr32(hw, NGBE_MDIOSCD, command);
345 
346 	/* wait for completion */
347 	if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY,
348 		0, NULL, 100, 100)) {
349 		TLOG_DEBUG("PHY write cmd didn't complete\n");
350 		return NGBE_ERR_PHY;
351 	}
352 
353 	return 0;
354 }
355 
356 /**
357  *  ngbe_write_phy_reg - Writes a value to specified PHY register
358  *  using SWFW lock- this function is needed in most cases
359  *  @hw: pointer to hardware structure
360  *  @reg_addr: 32 bit PHY register to write
361  *  @device_type: 5 bit device type
362  *  @phy_data: Data to write to the PHY register
363  **/
364 s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr,
365 				u32 device_type, u16 phy_data)
366 {
367 	s32 err;
368 	u32 gssr = hw->phy.phy_semaphore_mask;
369 
370 	DEBUGFUNC("ngbe_write_phy_reg");
371 
372 	if (hw->mac.acquire_swfw_sync(hw, gssr))
373 		err = NGBE_ERR_SWFW_SYNC;
374 
375 	err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type,
376 					 phy_data);
377 
378 	hw->mac.release_swfw_sync(hw, gssr);
379 
380 	return err;
381 }
382 
383 /**
384  *  ngbe_init_phy - PHY specific init
385  *  @hw: pointer to hardware structure
386  *
387  *  Initialize any function pointers that were not able to be
388  *  set during init_shared_code because the PHY type was
389  *  not known.
390  *
391  **/
392 s32 ngbe_init_phy(struct ngbe_hw *hw)
393 {
394 	struct ngbe_phy_info *phy = &hw->phy;
395 	s32 err = 0;
396 
397 	DEBUGFUNC("ngbe_init_phy");
398 
399 	hw->phy.addr = 0;
400 
401 	switch (hw->sub_device_id) {
402 	case NGBE_SUB_DEV_ID_EM_RTL_SGMII:
403 		hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl;
404 		hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl;
405 		break;
406 	case NGBE_SUB_DEV_ID_EM_MVL_RGMII:
407 	case NGBE_SUB_DEV_ID_EM_MVL_SFP:
408 		hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl;
409 		hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl;
410 		break;
411 	case NGBE_SUB_DEV_ID_EM_YT8521S_SFP:
412 		hw->phy.read_reg_unlocked = ngbe_read_phy_reg_yt;
413 		hw->phy.write_reg_unlocked = ngbe_write_phy_reg_yt;
414 		break;
415 	default:
416 		break;
417 	}
418 
419 	hw->phy.phy_semaphore_mask = NGBE_MNGSEM_SWPHY;
420 
421 	/* Identify the PHY */
422 	err = phy->identify(hw);
423 	if (err == NGBE_ERR_PHY_ADDR_INVALID)
424 		goto init_phy_ops_out;
425 
426 	/* Set necessary function pointers based on PHY type */
427 	switch (hw->phy.type) {
428 	case ngbe_phy_rtl:
429 		hw->phy.init_hw = ngbe_init_phy_rtl;
430 		hw->phy.check_link = ngbe_check_phy_link_rtl;
431 		hw->phy.setup_link = ngbe_setup_phy_link_rtl;
432 		break;
433 	case ngbe_phy_mvl:
434 	case ngbe_phy_mvl_sfi:
435 		hw->phy.init_hw = ngbe_init_phy_mvl;
436 		hw->phy.check_link = ngbe_check_phy_link_mvl;
437 		hw->phy.setup_link = ngbe_setup_phy_link_mvl;
438 		break;
439 	case ngbe_phy_yt8521s:
440 	case ngbe_phy_yt8521s_sfi:
441 		hw->phy.init_hw = ngbe_init_phy_yt;
442 		hw->phy.check_link = ngbe_check_phy_link_yt;
443 		hw->phy.setup_link = ngbe_setup_phy_link_yt;
444 	default:
445 		break;
446 	}
447 
448 init_phy_ops_out:
449 	return err;
450 }
451 
452