1
2
3
4
5
6#include "ngbe_hw.h"
7#include "ngbe_phy.h"
8
9s32 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
41
42
43
44
45
46static 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
66
67
68
69
70s32 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
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
95
96
97
98
99
100
101
102s32 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
119
120
121
122
123bool 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
147
148
149
150s32 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
177
178
179
180enum 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
212
213
214s32 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
227 if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP)
228 return err;
229
230
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
255
256
257
258
259
260
261s32 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
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
279
280
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
296
297
298
299
300
301
302s32 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
323
324
325
326
327
328
329s32 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
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
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
358
359
360
361
362
363
364s32 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
385
386
387
388
389
390
391
392s32 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
422 err = phy->identify(hw);
423 if (err == NGBE_ERR_PHY_ADDR_INVALID)
424 goto init_phy_ops_out;
425
426
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 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_rtl;
433 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_rtl;
434 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_rtl;
435 break;
436 case ngbe_phy_mvl:
437 case ngbe_phy_mvl_sfi:
438 hw->phy.init_hw = ngbe_init_phy_mvl;
439 hw->phy.check_link = ngbe_check_phy_link_mvl;
440 hw->phy.setup_link = ngbe_setup_phy_link_mvl;
441 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_mvl;
442 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_mvl;
443 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_mvl;
444 break;
445 case ngbe_phy_yt8521s:
446 case ngbe_phy_yt8521s_sfi:
447 hw->phy.init_hw = ngbe_init_phy_yt;
448 hw->phy.check_link = ngbe_check_phy_link_yt;
449 hw->phy.setup_link = ngbe_setup_phy_link_yt;
450 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_yt;
451 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_yt;
452 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_yt;
453 default:
454 break;
455 }
456
457init_phy_ops_out:
458 return err;
459}
460
461