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