1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2018 Intel Corporation */ |
3 | |
4 | #include "igc_phy.h" |
5 | |
6 | /** |
7 | * igc_check_reset_block - Check if PHY reset is blocked |
8 | * @hw: pointer to the HW structure |
9 | * |
10 | * Read the PHY management control register and check whether a PHY reset |
11 | * is blocked. If a reset is not blocked return 0, otherwise |
12 | * return IGC_ERR_BLK_PHY_RESET (12). |
13 | */ |
14 | s32 igc_check_reset_block(struct igc_hw *hw) |
15 | { |
16 | u32 manc; |
17 | |
18 | manc = rd32(IGC_MANC); |
19 | |
20 | return (manc & IGC_MANC_BLK_PHY_RST_ON_IDE) ? |
21 | IGC_ERR_BLK_PHY_RESET : 0; |
22 | } |
23 | |
24 | /** |
25 | * igc_get_phy_id - Retrieve the PHY ID and revision |
26 | * @hw: pointer to the HW structure |
27 | * |
28 | * Reads the PHY registers and stores the PHY ID and possibly the PHY |
29 | * revision in the hardware structure. |
30 | */ |
31 | s32 igc_get_phy_id(struct igc_hw *hw) |
32 | { |
33 | struct igc_phy_info *phy = &hw->phy; |
34 | s32 ret_val = 0; |
35 | u16 phy_id; |
36 | |
37 | ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); |
38 | if (ret_val) |
39 | goto out; |
40 | |
41 | phy->id = (u32)(phy_id << 16); |
42 | usleep_range(min: 200, max: 500); |
43 | ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); |
44 | if (ret_val) |
45 | goto out; |
46 | |
47 | phy->id |= (u32)(phy_id & PHY_REVISION_MASK); |
48 | phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); |
49 | |
50 | out: |
51 | return ret_val; |
52 | } |
53 | |
54 | /** |
55 | * igc_phy_has_link - Polls PHY for link |
56 | * @hw: pointer to the HW structure |
57 | * @iterations: number of times to poll for link |
58 | * @usec_interval: delay between polling attempts |
59 | * @success: pointer to whether polling was successful or not |
60 | * |
61 | * Polls the PHY status register for link, 'iterations' number of times. |
62 | */ |
63 | s32 igc_phy_has_link(struct igc_hw *hw, u32 iterations, |
64 | u32 usec_interval, bool *success) |
65 | { |
66 | u16 i, phy_status; |
67 | s32 ret_val = 0; |
68 | |
69 | for (i = 0; i < iterations; i++) { |
70 | /* Some PHYs require the PHY_STATUS register to be read |
71 | * twice due to the link bit being sticky. No harm doing |
72 | * it across the board. |
73 | */ |
74 | ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); |
75 | if (ret_val && usec_interval > 0) { |
76 | /* If the first read fails, another entity may have |
77 | * ownership of the resources, wait and try again to |
78 | * see if they have relinquished the resources yet. |
79 | */ |
80 | if (usec_interval >= 1000) |
81 | mdelay(usec_interval / 1000); |
82 | else |
83 | udelay(usec_interval); |
84 | } |
85 | ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); |
86 | if (ret_val) |
87 | break; |
88 | if (phy_status & MII_SR_LINK_STATUS) |
89 | break; |
90 | if (usec_interval >= 1000) |
91 | mdelay(usec_interval / 1000); |
92 | else |
93 | udelay(usec_interval); |
94 | } |
95 | |
96 | *success = (i < iterations) ? true : false; |
97 | |
98 | return ret_val; |
99 | } |
100 | |
101 | /** |
102 | * igc_power_up_phy_copper - Restore copper link in case of PHY power down |
103 | * @hw: pointer to the HW structure |
104 | * |
105 | * In the case of a PHY power down to save power, or to turn off link during a |
106 | * driver unload, restore the link to previous settings. |
107 | */ |
108 | void igc_power_up_phy_copper(struct igc_hw *hw) |
109 | { |
110 | u16 mii_reg = 0; |
111 | |
112 | /* The PHY will retain its settings across a power down/up cycle */ |
113 | hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); |
114 | mii_reg &= ~MII_CR_POWER_DOWN; |
115 | hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); |
116 | } |
117 | |
118 | /** |
119 | * igc_power_down_phy_copper - Power down copper PHY |
120 | * @hw: pointer to the HW structure |
121 | * |
122 | * Power down PHY to save power when interface is down and wake on lan |
123 | * is not enabled. |
124 | */ |
125 | void igc_power_down_phy_copper(struct igc_hw *hw) |
126 | { |
127 | u16 mii_reg = 0; |
128 | |
129 | /* The PHY will retain its settings across a power down/up cycle */ |
130 | hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); |
131 | mii_reg |= MII_CR_POWER_DOWN; |
132 | |
133 | /* Temporary workaround - should be removed when PHY will implement |
134 | * IEEE registers as properly |
135 | */ |
136 | /* hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);*/ |
137 | usleep_range(min: 1000, max: 2000); |
138 | } |
139 | |
140 | /** |
141 | * igc_check_downshift - Checks whether a downshift in speed occurred |
142 | * @hw: pointer to the HW structure |
143 | * |
144 | * A downshift is detected by querying the PHY link health. |
145 | */ |
146 | void igc_check_downshift(struct igc_hw *hw) |
147 | { |
148 | struct igc_phy_info *phy = &hw->phy; |
149 | |
150 | /* speed downshift not supported */ |
151 | phy->speed_downgraded = false; |
152 | } |
153 | |
154 | /** |
155 | * igc_phy_hw_reset - PHY hardware reset |
156 | * @hw: pointer to the HW structure |
157 | * |
158 | * Verify the reset block is not blocking us from resetting. Acquire |
159 | * semaphore (if necessary) and read/set/write the device control reset |
160 | * bit in the PHY. Wait the appropriate delay time for the device to |
161 | * reset and release the semaphore (if necessary). |
162 | */ |
163 | s32 igc_phy_hw_reset(struct igc_hw *hw) |
164 | { |
165 | struct igc_phy_info *phy = &hw->phy; |
166 | u32 phpm = 0, timeout = 10000; |
167 | s32 ret_val; |
168 | u32 ctrl; |
169 | |
170 | ret_val = igc_check_reset_block(hw); |
171 | if (ret_val) { |
172 | ret_val = 0; |
173 | goto out; |
174 | } |
175 | |
176 | ret_val = phy->ops.acquire(hw); |
177 | if (ret_val) |
178 | goto out; |
179 | |
180 | phpm = rd32(IGC_I225_PHPM); |
181 | |
182 | ctrl = rd32(IGC_CTRL); |
183 | wr32(IGC_CTRL, ctrl | IGC_CTRL_PHY_RST); |
184 | wrfl(); |
185 | |
186 | udelay(phy->reset_delay_us); |
187 | |
188 | wr32(IGC_CTRL, ctrl); |
189 | wrfl(); |
190 | |
191 | /* SW should guarantee 100us for the completion of the PHY reset */ |
192 | usleep_range(min: 100, max: 150); |
193 | do { |
194 | phpm = rd32(IGC_I225_PHPM); |
195 | timeout--; |
196 | udelay(1); |
197 | } while (!(phpm & IGC_PHY_RST_COMP) && timeout); |
198 | |
199 | if (!timeout) |
200 | hw_dbg("Timeout is expired after a phy reset\n" ); |
201 | |
202 | usleep_range(min: 100, max: 150); |
203 | |
204 | phy->ops.release(hw); |
205 | |
206 | out: |
207 | return ret_val; |
208 | } |
209 | |
210 | /** |
211 | * igc_phy_setup_autoneg - Configure PHY for auto-negotiation |
212 | * @hw: pointer to the HW structure |
213 | * |
214 | * Reads the MII auto-neg advertisement register and/or the 1000T control |
215 | * register and if the PHY is already setup for auto-negotiation, then |
216 | * return successful. Otherwise, setup advertisement and flow control to |
217 | * the appropriate values for the wanted auto-negotiation. |
218 | */ |
219 | static s32 igc_phy_setup_autoneg(struct igc_hw *hw) |
220 | { |
221 | struct igc_phy_info *phy = &hw->phy; |
222 | u16 aneg_multigbt_an_ctrl = 0; |
223 | u16 mii_1000t_ctrl_reg = 0; |
224 | u16 mii_autoneg_adv_reg; |
225 | s32 ret_val; |
226 | |
227 | phy->autoneg_advertised &= phy->autoneg_mask; |
228 | |
229 | /* Read the MII Auto-Neg Advertisement Register (Address 4). */ |
230 | ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); |
231 | if (ret_val) |
232 | return ret_val; |
233 | |
234 | if (phy->autoneg_mask & ADVERTISE_1000_FULL) { |
235 | /* Read the MII 1000Base-T Control Register (Address 9). */ |
236 | ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, |
237 | &mii_1000t_ctrl_reg); |
238 | if (ret_val) |
239 | return ret_val; |
240 | } |
241 | |
242 | if (phy->autoneg_mask & ADVERTISE_2500_FULL) { |
243 | /* Read the MULTI GBT AN Control Register - reg 7.32 */ |
244 | ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK << |
245 | MMD_DEVADDR_SHIFT) | |
246 | ANEG_MULTIGBT_AN_CTRL, |
247 | &aneg_multigbt_an_ctrl); |
248 | |
249 | if (ret_val) |
250 | return ret_val; |
251 | } |
252 | |
253 | /* Need to parse both autoneg_advertised and fc and set up |
254 | * the appropriate PHY registers. First we will parse for |
255 | * autoneg_advertised software override. Since we can advertise |
256 | * a plethora of combinations, we need to check each bit |
257 | * individually. |
258 | */ |
259 | |
260 | /* First we clear all the 10/100 mb speed bits in the Auto-Neg |
261 | * Advertisement Register (Address 4) and the 1000 mb speed bits in |
262 | * the 1000Base-T Control Register (Address 9). |
263 | */ |
264 | mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS | |
265 | NWAY_AR_100TX_HD_CAPS | |
266 | NWAY_AR_10T_FD_CAPS | |
267 | NWAY_AR_10T_HD_CAPS); |
268 | mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); |
269 | |
270 | hw_dbg("autoneg_advertised %x\n" , phy->autoneg_advertised); |
271 | |
272 | /* Do we want to advertise 10 Mb Half Duplex? */ |
273 | if (phy->autoneg_advertised & ADVERTISE_10_HALF) { |
274 | hw_dbg("Advertise 10mb Half duplex\n" ); |
275 | mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; |
276 | } |
277 | |
278 | /* Do we want to advertise 10 Mb Full Duplex? */ |
279 | if (phy->autoneg_advertised & ADVERTISE_10_FULL) { |
280 | hw_dbg("Advertise 10mb Full duplex\n" ); |
281 | mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; |
282 | } |
283 | |
284 | /* Do we want to advertise 100 Mb Half Duplex? */ |
285 | if (phy->autoneg_advertised & ADVERTISE_100_HALF) { |
286 | hw_dbg("Advertise 100mb Half duplex\n" ); |
287 | mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; |
288 | } |
289 | |
290 | /* Do we want to advertise 100 Mb Full Duplex? */ |
291 | if (phy->autoneg_advertised & ADVERTISE_100_FULL) { |
292 | hw_dbg("Advertise 100mb Full duplex\n" ); |
293 | mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; |
294 | } |
295 | |
296 | /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ |
297 | if (phy->autoneg_advertised & ADVERTISE_1000_HALF) |
298 | hw_dbg("Advertise 1000mb Half duplex request denied!\n" ); |
299 | |
300 | /* Do we want to advertise 1000 Mb Full Duplex? */ |
301 | if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { |
302 | hw_dbg("Advertise 1000mb Full duplex\n" ); |
303 | mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; |
304 | } |
305 | |
306 | /* We do not allow the Phy to advertise 2500 Mb Half Duplex */ |
307 | if (phy->autoneg_advertised & ADVERTISE_2500_HALF) |
308 | hw_dbg("Advertise 2500mb Half duplex request denied!\n" ); |
309 | |
310 | /* Do we want to advertise 2500 Mb Full Duplex? */ |
311 | if (phy->autoneg_advertised & ADVERTISE_2500_FULL) { |
312 | hw_dbg("Advertise 2500mb Full duplex\n" ); |
313 | aneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS; |
314 | } else { |
315 | aneg_multigbt_an_ctrl &= ~CR_2500T_FD_CAPS; |
316 | } |
317 | |
318 | /* Check for a software override of the flow control settings, and |
319 | * setup the PHY advertisement registers accordingly. If |
320 | * auto-negotiation is enabled, then software will have to set the |
321 | * "PAUSE" bits to the correct value in the Auto-Negotiation |
322 | * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- |
323 | * negotiation. |
324 | * |
325 | * The possible values of the "fc" parameter are: |
326 | * 0: Flow control is completely disabled |
327 | * 1: Rx flow control is enabled (we can receive pause frames |
328 | * but not send pause frames). |
329 | * 2: Tx flow control is enabled (we can send pause frames |
330 | * but we do not support receiving pause frames). |
331 | * 3: Both Rx and Tx flow control (symmetric) are enabled. |
332 | * other: No software override. The flow control configuration |
333 | * in the EEPROM is used. |
334 | */ |
335 | switch (hw->fc.current_mode) { |
336 | case igc_fc_none: |
337 | /* Flow control (Rx & Tx) is completely disabled by a |
338 | * software over-ride. |
339 | */ |
340 | mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); |
341 | break; |
342 | case igc_fc_rx_pause: |
343 | /* Rx Flow control is enabled, and Tx Flow control is |
344 | * disabled, by a software over-ride. |
345 | * |
346 | * Since there really isn't a way to advertise that we are |
347 | * capable of Rx Pause ONLY, we will advertise that we |
348 | * support both symmetric and asymmetric Rx PAUSE. Later |
349 | * (in igc_config_fc_after_link_up) we will disable the |
350 | * hw's ability to send PAUSE frames. |
351 | */ |
352 | mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); |
353 | break; |
354 | case igc_fc_tx_pause: |
355 | /* Tx Flow control is enabled, and Rx Flow control is |
356 | * disabled, by a software over-ride. |
357 | */ |
358 | mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; |
359 | mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; |
360 | break; |
361 | case igc_fc_full: |
362 | /* Flow control (both Rx and Tx) is enabled by a software |
363 | * over-ride. |
364 | */ |
365 | mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); |
366 | break; |
367 | default: |
368 | hw_dbg("Flow control param set incorrectly\n" ); |
369 | return -IGC_ERR_CONFIG; |
370 | } |
371 | |
372 | ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); |
373 | if (ret_val) |
374 | return ret_val; |
375 | |
376 | hw_dbg("Auto-Neg Advertising %x\n" , mii_autoneg_adv_reg); |
377 | |
378 | if (phy->autoneg_mask & ADVERTISE_1000_FULL) |
379 | ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, |
380 | mii_1000t_ctrl_reg); |
381 | |
382 | if (phy->autoneg_mask & ADVERTISE_2500_FULL) |
383 | ret_val = phy->ops.write_reg(hw, |
384 | (STANDARD_AN_REG_MASK << |
385 | MMD_DEVADDR_SHIFT) | |
386 | ANEG_MULTIGBT_AN_CTRL, |
387 | aneg_multigbt_an_ctrl); |
388 | |
389 | return ret_val; |
390 | } |
391 | |
392 | /** |
393 | * igc_wait_autoneg - Wait for auto-neg completion |
394 | * @hw: pointer to the HW structure |
395 | * |
396 | * Waits for auto-negotiation to complete or for the auto-negotiation time |
397 | * limit to expire, which ever happens first. |
398 | */ |
399 | static s32 igc_wait_autoneg(struct igc_hw *hw) |
400 | { |
401 | u16 i, phy_status; |
402 | s32 ret_val = 0; |
403 | |
404 | /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ |
405 | for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { |
406 | ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); |
407 | if (ret_val) |
408 | break; |
409 | ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); |
410 | if (ret_val) |
411 | break; |
412 | if (phy_status & MII_SR_AUTONEG_COMPLETE) |
413 | break; |
414 | msleep(msecs: 100); |
415 | } |
416 | |
417 | /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation |
418 | * has completed. |
419 | */ |
420 | return ret_val; |
421 | } |
422 | |
423 | /** |
424 | * igc_copper_link_autoneg - Setup/Enable autoneg for copper link |
425 | * @hw: pointer to the HW structure |
426 | * |
427 | * Performs initial bounds checking on autoneg advertisement parameter, then |
428 | * configure to advertise the full capability. Setup the PHY to autoneg |
429 | * and restart the negotiation process between the link partner. If |
430 | * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. |
431 | */ |
432 | static s32 igc_copper_link_autoneg(struct igc_hw *hw) |
433 | { |
434 | struct igc_phy_info *phy = &hw->phy; |
435 | u16 phy_ctrl; |
436 | s32 ret_val; |
437 | |
438 | /* Perform some bounds checking on the autoneg advertisement |
439 | * parameter. |
440 | */ |
441 | phy->autoneg_advertised &= phy->autoneg_mask; |
442 | |
443 | /* If autoneg_advertised is zero, we assume it was not defaulted |
444 | * by the calling code so we set to advertise full capability. |
445 | */ |
446 | if (phy->autoneg_advertised == 0) |
447 | phy->autoneg_advertised = phy->autoneg_mask; |
448 | |
449 | hw_dbg("Reconfiguring auto-neg advertisement params\n" ); |
450 | ret_val = igc_phy_setup_autoneg(hw); |
451 | if (ret_val) { |
452 | hw_dbg("Error Setting up Auto-Negotiation\n" ); |
453 | goto out; |
454 | } |
455 | hw_dbg("Restarting Auto-Neg\n" ); |
456 | |
457 | /* Restart auto-negotiation by setting the Auto Neg Enable bit and |
458 | * the Auto Neg Restart bit in the PHY control register. |
459 | */ |
460 | ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); |
461 | if (ret_val) |
462 | goto out; |
463 | |
464 | phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); |
465 | ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); |
466 | if (ret_val) |
467 | goto out; |
468 | |
469 | /* Does the user want to wait for Auto-Neg to complete here, or |
470 | * check at a later time (for example, callback routine). |
471 | */ |
472 | if (phy->autoneg_wait_to_complete) { |
473 | ret_val = igc_wait_autoneg(hw); |
474 | if (ret_val) { |
475 | hw_dbg("Error while waiting for autoneg to complete\n" ); |
476 | goto out; |
477 | } |
478 | } |
479 | |
480 | hw->mac.get_link_status = true; |
481 | |
482 | out: |
483 | return ret_val; |
484 | } |
485 | |
486 | /** |
487 | * igc_setup_copper_link - Configure copper link settings |
488 | * @hw: pointer to the HW structure |
489 | * |
490 | * Calls the appropriate function to configure the link for auto-neg or forced |
491 | * speed and duplex. Then we check for link, once link is established calls |
492 | * to configure collision distance and flow control are called. If link is |
493 | * not established, we return -IGC_ERR_PHY (-2). |
494 | */ |
495 | s32 igc_setup_copper_link(struct igc_hw *hw) |
496 | { |
497 | s32 ret_val = 0; |
498 | bool link; |
499 | |
500 | if (hw->mac.autoneg) { |
501 | /* Setup autoneg and flow control advertisement and perform |
502 | * autonegotiation. |
503 | */ |
504 | ret_val = igc_copper_link_autoneg(hw); |
505 | if (ret_val) |
506 | goto out; |
507 | } else { |
508 | /* PHY will be set to 10H, 10F, 100H or 100F |
509 | * depending on user settings. |
510 | */ |
511 | hw_dbg("Forcing Speed and Duplex\n" ); |
512 | ret_val = hw->phy.ops.force_speed_duplex(hw); |
513 | if (ret_val) { |
514 | hw_dbg("Error Forcing Speed and Duplex\n" ); |
515 | goto out; |
516 | } |
517 | } |
518 | |
519 | /* Check link status. Wait up to 100 microseconds for link to become |
520 | * valid. |
521 | */ |
522 | ret_val = igc_phy_has_link(hw, COPPER_LINK_UP_LIMIT, usec_interval: 10, success: &link); |
523 | if (ret_val) |
524 | goto out; |
525 | |
526 | if (link) { |
527 | hw_dbg("Valid link established!!!\n" ); |
528 | igc_config_collision_dist(hw); |
529 | ret_val = igc_config_fc_after_link_up(hw); |
530 | } else { |
531 | hw_dbg("Unable to establish link!!!\n" ); |
532 | } |
533 | |
534 | out: |
535 | return ret_val; |
536 | } |
537 | |
538 | /** |
539 | * igc_read_phy_reg_mdic - Read MDI control register |
540 | * @hw: pointer to the HW structure |
541 | * @offset: register offset to be read |
542 | * @data: pointer to the read data |
543 | * |
544 | * Reads the MDI control register in the PHY at offset and stores the |
545 | * information read to data. |
546 | */ |
547 | static s32 igc_read_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 *data) |
548 | { |
549 | struct igc_phy_info *phy = &hw->phy; |
550 | u32 i, mdic = 0; |
551 | s32 ret_val = 0; |
552 | |
553 | if (offset > MAX_PHY_REG_ADDRESS) { |
554 | hw_dbg("PHY Address %d is out of range\n" , offset); |
555 | ret_val = -IGC_ERR_PARAM; |
556 | goto out; |
557 | } |
558 | |
559 | /* Set up Op-code, Phy Address, and register offset in the MDI |
560 | * Control register. The MAC will take care of interfacing with the |
561 | * PHY to retrieve the desired data. |
562 | */ |
563 | mdic = ((offset << IGC_MDIC_REG_SHIFT) | |
564 | (phy->addr << IGC_MDIC_PHY_SHIFT) | |
565 | (IGC_MDIC_OP_READ)); |
566 | |
567 | wr32(IGC_MDIC, mdic); |
568 | |
569 | /* Poll the ready bit to see if the MDI read completed |
570 | * Increasing the time out as testing showed failures with |
571 | * the lower time out |
572 | */ |
573 | for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) { |
574 | udelay(50); |
575 | mdic = rd32(IGC_MDIC); |
576 | if (mdic & IGC_MDIC_READY) |
577 | break; |
578 | } |
579 | if (!(mdic & IGC_MDIC_READY)) { |
580 | hw_dbg("MDI Read did not complete\n" ); |
581 | ret_val = -IGC_ERR_PHY; |
582 | goto out; |
583 | } |
584 | if (mdic & IGC_MDIC_ERROR) { |
585 | hw_dbg("MDI Error\n" ); |
586 | ret_val = -IGC_ERR_PHY; |
587 | goto out; |
588 | } |
589 | *data = (u16)mdic; |
590 | |
591 | out: |
592 | return ret_val; |
593 | } |
594 | |
595 | /** |
596 | * igc_write_phy_reg_mdic - Write MDI control register |
597 | * @hw: pointer to the HW structure |
598 | * @offset: register offset to write to |
599 | * @data: data to write to register at offset |
600 | * |
601 | * Writes data to MDI control register in the PHY at offset. |
602 | */ |
603 | static s32 igc_write_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 data) |
604 | { |
605 | struct igc_phy_info *phy = &hw->phy; |
606 | u32 i, mdic = 0; |
607 | s32 ret_val = 0; |
608 | |
609 | if (offset > MAX_PHY_REG_ADDRESS) { |
610 | hw_dbg("PHY Address %d is out of range\n" , offset); |
611 | ret_val = -IGC_ERR_PARAM; |
612 | goto out; |
613 | } |
614 | |
615 | /* Set up Op-code, Phy Address, and register offset in the MDI |
616 | * Control register. The MAC will take care of interfacing with the |
617 | * PHY to write the desired data. |
618 | */ |
619 | mdic = (((u32)data) | |
620 | (offset << IGC_MDIC_REG_SHIFT) | |
621 | (phy->addr << IGC_MDIC_PHY_SHIFT) | |
622 | (IGC_MDIC_OP_WRITE)); |
623 | |
624 | wr32(IGC_MDIC, mdic); |
625 | |
626 | /* Poll the ready bit to see if the MDI read completed |
627 | * Increasing the time out as testing showed failures with |
628 | * the lower time out |
629 | */ |
630 | for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) { |
631 | udelay(50); |
632 | mdic = rd32(IGC_MDIC); |
633 | if (mdic & IGC_MDIC_READY) |
634 | break; |
635 | } |
636 | if (!(mdic & IGC_MDIC_READY)) { |
637 | hw_dbg("MDI Write did not complete\n" ); |
638 | ret_val = -IGC_ERR_PHY; |
639 | goto out; |
640 | } |
641 | if (mdic & IGC_MDIC_ERROR) { |
642 | hw_dbg("MDI Error\n" ); |
643 | ret_val = -IGC_ERR_PHY; |
644 | goto out; |
645 | } |
646 | |
647 | out: |
648 | return ret_val; |
649 | } |
650 | |
651 | /** |
652 | * __igc_access_xmdio_reg - Read/write XMDIO register |
653 | * @hw: pointer to the HW structure |
654 | * @address: XMDIO address to program |
655 | * @dev_addr: device address to program |
656 | * @data: pointer to value to read/write from/to the XMDIO address |
657 | * @read: boolean flag to indicate read or write |
658 | */ |
659 | static s32 __igc_access_xmdio_reg(struct igc_hw *hw, u16 address, |
660 | u8 dev_addr, u16 *data, bool read) |
661 | { |
662 | s32 ret_val; |
663 | |
664 | ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, dev_addr); |
665 | if (ret_val) |
666 | return ret_val; |
667 | |
668 | ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAAD, address); |
669 | if (ret_val) |
670 | return ret_val; |
671 | |
672 | ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, IGC_MMDAC_FUNC_DATA | |
673 | dev_addr); |
674 | if (ret_val) |
675 | return ret_val; |
676 | |
677 | if (read) |
678 | ret_val = hw->phy.ops.read_reg(hw, IGC_MMDAAD, data); |
679 | else |
680 | ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAAD, *data); |
681 | if (ret_val) |
682 | return ret_val; |
683 | |
684 | /* Recalibrate the device back to 0 */ |
685 | ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, 0); |
686 | if (ret_val) |
687 | return ret_val; |
688 | |
689 | return ret_val; |
690 | } |
691 | |
692 | /** |
693 | * igc_read_xmdio_reg - Read XMDIO register |
694 | * @hw: pointer to the HW structure |
695 | * @addr: XMDIO address to program |
696 | * @dev_addr: device address to program |
697 | * @data: value to be read from the EMI address |
698 | */ |
699 | static s32 igc_read_xmdio_reg(struct igc_hw *hw, u16 addr, |
700 | u8 dev_addr, u16 *data) |
701 | { |
702 | return __igc_access_xmdio_reg(hw, address: addr, dev_addr, data, read: true); |
703 | } |
704 | |
705 | /** |
706 | * igc_write_xmdio_reg - Write XMDIO register |
707 | * @hw: pointer to the HW structure |
708 | * @addr: XMDIO address to program |
709 | * @dev_addr: device address to program |
710 | * @data: value to be written to the XMDIO address |
711 | */ |
712 | static s32 igc_write_xmdio_reg(struct igc_hw *hw, u16 addr, |
713 | u8 dev_addr, u16 data) |
714 | { |
715 | return __igc_access_xmdio_reg(hw, address: addr, dev_addr, data: &data, read: false); |
716 | } |
717 | |
718 | /** |
719 | * igc_write_phy_reg_gpy - Write GPY PHY register |
720 | * @hw: pointer to the HW structure |
721 | * @offset: register offset to write to |
722 | * @data: data to write at register offset |
723 | * |
724 | * Acquires semaphore, if necessary, then writes the data to PHY register |
725 | * at the offset. Release any acquired semaphores before exiting. |
726 | */ |
727 | s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data) |
728 | { |
729 | u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT; |
730 | s32 ret_val; |
731 | |
732 | offset = offset & GPY_REG_MASK; |
733 | |
734 | if (!dev_addr) { |
735 | ret_val = hw->phy.ops.acquire(hw); |
736 | if (ret_val) |
737 | return ret_val; |
738 | ret_val = igc_write_phy_reg_mdic(hw, offset, data); |
739 | hw->phy.ops.release(hw); |
740 | } else { |
741 | ret_val = igc_write_xmdio_reg(hw, addr: (u16)offset, dev_addr, |
742 | data); |
743 | } |
744 | |
745 | return ret_val; |
746 | } |
747 | |
748 | /** |
749 | * igc_read_phy_reg_gpy - Read GPY PHY register |
750 | * @hw: pointer to the HW structure |
751 | * @offset: lower half is register offset to read to |
752 | * upper half is MMD to use. |
753 | * @data: data to read at register offset |
754 | * |
755 | * Acquires semaphore, if necessary, then reads the data in the PHY register |
756 | * at the offset. Release any acquired semaphores before exiting. |
757 | */ |
758 | s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data) |
759 | { |
760 | u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT; |
761 | s32 ret_val; |
762 | |
763 | offset = offset & GPY_REG_MASK; |
764 | |
765 | if (!dev_addr) { |
766 | ret_val = hw->phy.ops.acquire(hw); |
767 | if (ret_val) |
768 | return ret_val; |
769 | ret_val = igc_read_phy_reg_mdic(hw, offset, data); |
770 | hw->phy.ops.release(hw); |
771 | } else { |
772 | ret_val = igc_read_xmdio_reg(hw, addr: (u16)offset, dev_addr, |
773 | data); |
774 | } |
775 | |
776 | return ret_val; |
777 | } |
778 | |
779 | /** |
780 | * igc_read_phy_fw_version - Read gPHY firmware version |
781 | * @hw: pointer to the HW structure |
782 | */ |
783 | u16 igc_read_phy_fw_version(struct igc_hw *hw) |
784 | { |
785 | struct igc_phy_info *phy = &hw->phy; |
786 | u16 gphy_version = 0; |
787 | u16 ret_val; |
788 | |
789 | /* NVM image version is reported as firmware version for i225 device */ |
790 | ret_val = phy->ops.read_reg(hw, IGC_GPHY_VERSION, &gphy_version); |
791 | if (ret_val) |
792 | hw_dbg("igc_phy: read wrong gphy version\n" ); |
793 | |
794 | return gphy_version; |
795 | } |
796 | |