aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/igc/igc_phy.c
diff options
context:
space:
mode:
authorSasha Neftin <sasha.neftin@intel.com>2018-10-11 03:17:34 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-10-17 16:56:55 -0400
commit4eb8080143a9d9fd513bacc65b2466c57983aaae (patch)
tree32923ea729cb92f3afbf68e7ca1698ed7db0b2ef /drivers/net/ethernet/intel/igc/igc_phy.c
parent5586838fe9ced0980e210b39d635ff3842297448 (diff)
igc: Add setup link functionality
Add link establishment methods Add auto negotiation methods Add read MAC address method Signed-off-by: Sasha Neftin <sasha.neftin@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/igc/igc_phy.c')
-rw-r--r--drivers/net/ethernet/intel/igc/igc_phy.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/igc/igc_phy.c b/drivers/net/ethernet/intel/igc/igc_phy.c
index 88583c1d4970..38e43e6fc1c7 100644
--- a/drivers/net/ethernet/intel/igc/igc_phy.c
+++ b/drivers/net/ethernet/intel/igc/igc_phy.c
@@ -3,6 +3,10 @@
3 3
4#include "igc_phy.h" 4#include "igc_phy.h"
5 5
6/* forward declaration */
7static s32 igc_phy_setup_autoneg(struct igc_hw *hw);
8static s32 igc_wait_autoneg(struct igc_hw *hw);
9
6/** 10/**
7 * igc_check_reset_block - Check if PHY reset is blocked 11 * igc_check_reset_block - Check if PHY reset is blocked
8 * @hw: pointer to the HW structure 12 * @hw: pointer to the HW structure
@@ -212,6 +216,336 @@ out:
212} 216}
213 217
214/** 218/**
219 * igc_copper_link_autoneg - Setup/Enable autoneg for copper link
220 * @hw: pointer to the HW structure
221 *
222 * Performs initial bounds checking on autoneg advertisement parameter, then
223 * configure to advertise the full capability. Setup the PHY to autoneg
224 * and restart the negotiation process between the link partner. If
225 * autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
226 */
227static s32 igc_copper_link_autoneg(struct igc_hw *hw)
228{
229 struct igc_phy_info *phy = &hw->phy;
230 u16 phy_ctrl;
231 s32 ret_val;
232
233 /* Perform some bounds checking on the autoneg advertisement
234 * parameter.
235 */
236 phy->autoneg_advertised &= phy->autoneg_mask;
237
238 /* If autoneg_advertised is zero, we assume it was not defaulted
239 * by the calling code so we set to advertise full capability.
240 */
241 if (phy->autoneg_advertised == 0)
242 phy->autoneg_advertised = phy->autoneg_mask;
243
244 hw_dbg("Reconfiguring auto-neg advertisement params\n");
245 ret_val = igc_phy_setup_autoneg(hw);
246 if (ret_val) {
247 hw_dbg("Error Setting up Auto-Negotiation\n");
248 goto out;
249 }
250 hw_dbg("Restarting Auto-Neg\n");
251
252 /* Restart auto-negotiation by setting the Auto Neg Enable bit and
253 * the Auto Neg Restart bit in the PHY control register.
254 */
255 ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
256 if (ret_val)
257 goto out;
258
259 phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
260 ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
261 if (ret_val)
262 goto out;
263
264 /* Does the user want to wait for Auto-Neg to complete here, or
265 * check at a later time (for example, callback routine).
266 */
267 if (phy->autoneg_wait_to_complete) {
268 ret_val = igc_wait_autoneg(hw);
269 if (ret_val) {
270 hw_dbg("Error while waiting for autoneg to complete\n");
271 goto out;
272 }
273 }
274
275 hw->mac.get_link_status = true;
276
277out:
278 return ret_val;
279}
280
281/**
282 * igc_wait_autoneg - Wait for auto-neg completion
283 * @hw: pointer to the HW structure
284 *
285 * Waits for auto-negotiation to complete or for the auto-negotiation time
286 * limit to expire, which ever happens first.
287 */
288static s32 igc_wait_autoneg(struct igc_hw *hw)
289{
290 u16 i, phy_status;
291 s32 ret_val = 0;
292
293 /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
294 for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
295 ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
296 if (ret_val)
297 break;
298 ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
299 if (ret_val)
300 break;
301 if (phy_status & MII_SR_AUTONEG_COMPLETE)
302 break;
303 msleep(100);
304 }
305
306 /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
307 * has completed.
308 */
309 return ret_val;
310}
311
312/**
313 * igc_phy_setup_autoneg - Configure PHY for auto-negotiation
314 * @hw: pointer to the HW structure
315 *
316 * Reads the MII auto-neg advertisement register and/or the 1000T control
317 * register and if the PHY is already setup for auto-negotiation, then
318 * return successful. Otherwise, setup advertisement and flow control to
319 * the appropriate values for the wanted auto-negotiation.
320 */
321static s32 igc_phy_setup_autoneg(struct igc_hw *hw)
322{
323 struct igc_phy_info *phy = &hw->phy;
324 u16 aneg_multigbt_an_ctrl = 0;
325 u16 mii_1000t_ctrl_reg = 0;
326 u16 mii_autoneg_adv_reg;
327 s32 ret_val;
328
329 phy->autoneg_advertised &= phy->autoneg_mask;
330
331 /* Read the MII Auto-Neg Advertisement Register (Address 4). */
332 ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
333 if (ret_val)
334 return ret_val;
335
336 if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
337 /* Read the MII 1000Base-T Control Register (Address 9). */
338 ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
339 &mii_1000t_ctrl_reg);
340 if (ret_val)
341 return ret_val;
342 }
343
344 if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
345 hw->phy.id == I225_I_PHY_ID) {
346 /* Read the MULTI GBT AN Control Register - reg 7.32 */
347 ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<
348 MMD_DEVADDR_SHIFT) |
349 ANEG_MULTIGBT_AN_CTRL,
350 &aneg_multigbt_an_ctrl);
351
352 if (ret_val)
353 return ret_val;
354 }
355
356 /* Need to parse both autoneg_advertised and fc and set up
357 * the appropriate PHY registers. First we will parse for
358 * autoneg_advertised software override. Since we can advertise
359 * a plethora of combinations, we need to check each bit
360 * individually.
361 */
362
363 /* First we clear all the 10/100 mb speed bits in the Auto-Neg
364 * Advertisement Register (Address 4) and the 1000 mb speed bits in
365 * the 1000Base-T Control Register (Address 9).
366 */
367 mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
368 NWAY_AR_100TX_HD_CAPS |
369 NWAY_AR_10T_FD_CAPS |
370 NWAY_AR_10T_HD_CAPS);
371 mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
372
373 hw_dbg("autoneg_advertised %x\n", phy->autoneg_advertised);
374
375 /* Do we want to advertise 10 Mb Half Duplex? */
376 if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
377 hw_dbg("Advertise 10mb Half duplex\n");
378 mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
379 }
380
381 /* Do we want to advertise 10 Mb Full Duplex? */
382 if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
383 hw_dbg("Advertise 10mb Full duplex\n");
384 mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
385 }
386
387 /* Do we want to advertise 100 Mb Half Duplex? */
388 if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
389 hw_dbg("Advertise 100mb Half duplex\n");
390 mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
391 }
392
393 /* Do we want to advertise 100 Mb Full Duplex? */
394 if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
395 hw_dbg("Advertise 100mb Full duplex\n");
396 mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
397 }
398
399 /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
400 if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
401 hw_dbg("Advertise 1000mb Half duplex request denied!\n");
402
403 /* Do we want to advertise 1000 Mb Full Duplex? */
404 if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
405 hw_dbg("Advertise 1000mb Full duplex\n");
406 mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
407 }
408
409 /* We do not allow the Phy to advertise 2500 Mb Half Duplex */
410 if (phy->autoneg_advertised & ADVERTISE_2500_HALF)
411 hw_dbg("Advertise 2500mb Half duplex request denied!\n");
412
413 /* Do we want to advertise 2500 Mb Full Duplex? */
414 if (phy->autoneg_advertised & ADVERTISE_2500_FULL) {
415 hw_dbg("Advertise 2500mb Full duplex\n");
416 aneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS;
417 } else {
418 aneg_multigbt_an_ctrl &= ~CR_2500T_FD_CAPS;
419 }
420
421 /* Check for a software override of the flow control settings, and
422 * setup the PHY advertisement registers accordingly. If
423 * auto-negotiation is enabled, then software will have to set the
424 * "PAUSE" bits to the correct value in the Auto-Negotiation
425 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
426 * negotiation.
427 *
428 * The possible values of the "fc" parameter are:
429 * 0: Flow control is completely disabled
430 * 1: Rx flow control is enabled (we can receive pause frames
431 * but not send pause frames).
432 * 2: Tx flow control is enabled (we can send pause frames
433 * but we do not support receiving pause frames).
434 * 3: Both Rx and Tx flow control (symmetric) are enabled.
435 * other: No software override. The flow control configuration
436 * in the EEPROM is used.
437 */
438 switch (hw->fc.current_mode) {
439 case igc_fc_none:
440 /* Flow control (Rx & Tx) is completely disabled by a
441 * software over-ride.
442 */
443 mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
444 break;
445 case igc_fc_rx_pause:
446 /* Rx Flow control is enabled, and Tx Flow control is
447 * disabled, by a software over-ride.
448 *
449 * Since there really isn't a way to advertise that we are
450 * capable of Rx Pause ONLY, we will advertise that we
451 * support both symmetric and asymmetric Rx PAUSE. Later
452 * (in igc_config_fc_after_link_up) we will disable the
453 * hw's ability to send PAUSE frames.
454 */
455 mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
456 break;
457 case igc_fc_tx_pause:
458 /* Tx Flow control is enabled, and Rx Flow control is
459 * disabled, by a software over-ride.
460 */
461 mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
462 mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
463 break;
464 case igc_fc_full:
465 /* Flow control (both Rx and Tx) is enabled by a software
466 * over-ride.
467 */
468 mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
469 break;
470 default:
471 hw_dbg("Flow control param set incorrectly\n");
472 return -IGC_ERR_CONFIG;
473 }
474
475 ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
476 if (ret_val)
477 return ret_val;
478
479 hw_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
480
481 if (phy->autoneg_mask & ADVERTISE_1000_FULL)
482 ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
483 mii_1000t_ctrl_reg);
484
485 if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
486 hw->phy.id == I225_I_PHY_ID)
487 ret_val = phy->ops.write_reg(hw,
488 (STANDARD_AN_REG_MASK <<
489 MMD_DEVADDR_SHIFT) |
490 ANEG_MULTIGBT_AN_CTRL,
491 aneg_multigbt_an_ctrl);
492
493 return ret_val;
494}
495
496/**
497 * igc_setup_copper_link - Configure copper link settings
498 * @hw: pointer to the HW structure
499 *
500 * Calls the appropriate function to configure the link for auto-neg or forced
501 * speed and duplex. Then we check for link, once link is established calls
502 * to configure collision distance and flow control are called. If link is
503 * not established, we return -IGC_ERR_PHY (-2).
504 */
505s32 igc_setup_copper_link(struct igc_hw *hw)
506{
507 s32 ret_val = 0;
508 bool link;
509
510 if (hw->mac.autoneg) {
511 /* Setup autoneg and flow control advertisement and perform
512 * autonegotiation.
513 */
514 ret_val = igc_copper_link_autoneg(hw);
515 if (ret_val)
516 goto out;
517 } else {
518 /* PHY will be set to 10H, 10F, 100H or 100F
519 * depending on user settings.
520 */
521 hw_dbg("Forcing Speed and Duplex\n");
522 ret_val = hw->phy.ops.force_speed_duplex(hw);
523 if (ret_val) {
524 hw_dbg("Error Forcing Speed and Duplex\n");
525 goto out;
526 }
527 }
528
529 /* Check link status. Wait up to 100 microseconds for link to become
530 * valid.
531 */
532 ret_val = igc_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link);
533 if (ret_val)
534 goto out;
535
536 if (link) {
537 hw_dbg("Valid link established!!!\n");
538 igc_config_collision_dist(hw);
539 ret_val = igc_config_fc_after_link_up(hw);
540 } else {
541 hw_dbg("Unable to establish link!!!\n");
542 }
543
544out:
545 return ret_val;
546}
547
548/**
215 * igc_read_phy_reg_mdic - Read MDI control register 549 * igc_read_phy_reg_mdic - Read MDI control register
216 * @hw: pointer to the HW structure 550 * @hw: pointer to the HW structure
217 * @offset: register offset to be read 551 * @offset: register offset to be read