aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/atl1c/atl1c_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/atl1c/atl1c_hw.c')
-rw-r--r--drivers/net/atl1c/atl1c_hw.c107
1 files changed, 92 insertions, 15 deletions
diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c
index f1389d664a21..d8501f060957 100644
--- a/drivers/net/atl1c/atl1c_hw.c
+++ b/drivers/net/atl1c/atl1c_hw.c
@@ -37,6 +37,9 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
37 if (data & TWSI_DEBUG_DEV_EXIST) 37 if (data & TWSI_DEBUG_DEV_EXIST)
38 return 1; 38 return 1;
39 39
40 AT_READ_REG(hw, REG_MASTER_CTRL, &data);
41 if (data & MASTER_CTRL_OTP_SEL)
42 return 1;
40 return 0; 43 return 0;
41} 44}
42 45
@@ -69,6 +72,8 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
69 u32 i; 72 u32 i;
70 u32 otp_ctrl_data; 73 u32 otp_ctrl_data;
71 u32 twsi_ctrl_data; 74 u32 twsi_ctrl_data;
75 u32 ltssm_ctrl_data;
76 u32 wol_data;
72 u8 eth_addr[ETH_ALEN]; 77 u8 eth_addr[ETH_ALEN];
73 u16 phy_data; 78 u16 phy_data;
74 bool raise_vol = false; 79 bool raise_vol = false;
@@ -104,6 +109,15 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
104 udelay(20); 109 udelay(20);
105 raise_vol = true; 110 raise_vol = true;
106 } 111 }
112 /* close open bit of ReadOnly*/
113 AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &ltssm_ctrl_data);
114 ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO;
115 AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data);
116
117 /* clear any WOL settings */
118 AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
119 AT_READ_REG(hw, REG_WOL_CTRL, &wol_data);
120
107 121
108 AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); 122 AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
109 twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; 123 twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
@@ -119,17 +133,15 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
119 } 133 }
120 /* Disable OTP_CLK */ 134 /* Disable OTP_CLK */
121 if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) { 135 if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) {
122 if (otp_ctrl_data & OTP_CTRL_CLK_EN) { 136 otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
123 otp_ctrl_data &= ~OTP_CTRL_CLK_EN; 137 AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
124 AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); 138 msleep(1);
125 AT_WRITE_FLUSH(hw);
126 msleep(1);
127 }
128 } 139 }
129 if (raise_vol) { 140 if (raise_vol) {
130 if (hw->nic_type == athr_l2c_b || 141 if (hw->nic_type == athr_l2c_b ||
131 hw->nic_type == athr_l2c_b2 || 142 hw->nic_type == athr_l2c_b2 ||
132 hw->nic_type == athr_l1d) { 143 hw->nic_type == athr_l1d ||
144 hw->nic_type == athr_l1d_2) {
133 atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); 145 atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
134 if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) 146 if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
135 goto out; 147 goto out;
@@ -456,14 +468,22 @@ int atl1c_phy_reset(struct atl1c_hw *hw)
456 468
457 if (hw->nic_type == athr_l2c_b || 469 if (hw->nic_type == athr_l2c_b ||
458 hw->nic_type == athr_l2c_b2 || 470 hw->nic_type == athr_l2c_b2 ||
459 hw->nic_type == athr_l1d) { 471 hw->nic_type == athr_l1d ||
472 hw->nic_type == athr_l1d_2) {
460 atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); 473 atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
461 atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); 474 atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
462 atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7); 475 atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7);
463 msleep(20); 476 msleep(20);
464 } 477 }
465 478 if (hw->nic_type == athr_l1d) {
466 /*Enable PHY LinkChange Interrupt */ 479 atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
480 atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D);
481 }
482 if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2
483 || hw->nic_type == athr_l2c || hw->nic_type == athr_l2c) {
484 atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
485 atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
486 }
467 err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data); 487 err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
468 if (err) { 488 if (err) {
469 if (netif_msg_hw(adapter)) 489 if (netif_msg_hw(adapter))
@@ -482,12 +502,10 @@ int atl1c_phy_init(struct atl1c_hw *hw)
482 struct pci_dev *pdev = adapter->pdev; 502 struct pci_dev *pdev = adapter->pdev;
483 int ret_val; 503 int ret_val;
484 u16 mii_bmcr_data = BMCR_RESET; 504 u16 mii_bmcr_data = BMCR_RESET;
485 u16 phy_id1, phy_id2;
486 505
487 if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) || 506 if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) ||
488 (atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) { 507 (atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) {
489 if (netif_msg_link(adapter)) 508 dev_err(&pdev->dev, "Error get phy ID\n");
490 dev_err(&pdev->dev, "Error get phy ID\n");
491 return -1; 509 return -1;
492 } 510 }
493 switch (hw->media_type) { 511 switch (hw->media_type) {
@@ -572,6 +590,65 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
572 return 0; 590 return 0;
573} 591}
574 592
593int atl1c_phy_power_saving(struct atl1c_hw *hw)
594{
595 struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
596 struct pci_dev *pdev = adapter->pdev;
597 int ret = 0;
598 u16 autoneg_advertised = ADVERTISED_10baseT_Half;
599 u16 save_autoneg_advertised;
600 u16 phy_data;
601 u16 mii_lpa_data;
602 u16 speed = SPEED_0;
603 u16 duplex = FULL_DUPLEX;
604 int i;
605
606 atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
607 atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
608 if (phy_data & BMSR_LSTATUS) {
609 atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data);
610 if (mii_lpa_data & LPA_10FULL)
611 autoneg_advertised = ADVERTISED_10baseT_Full;
612 else if (mii_lpa_data & LPA_10HALF)
613 autoneg_advertised = ADVERTISED_10baseT_Half;
614 else if (mii_lpa_data & LPA_100HALF)
615 autoneg_advertised = ADVERTISED_100baseT_Half;
616 else if (mii_lpa_data & LPA_100FULL)
617 autoneg_advertised = ADVERTISED_100baseT_Full;
618
619 save_autoneg_advertised = hw->autoneg_advertised;
620 hw->phy_configured = false;
621 hw->autoneg_advertised = autoneg_advertised;
622 if (atl1c_restart_autoneg(hw) != 0) {
623 dev_dbg(&pdev->dev, "phy autoneg failed\n");
624 ret = -1;
625 }
626 hw->autoneg_advertised = save_autoneg_advertised;
627
628 if (mii_lpa_data) {
629 for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
630 mdelay(100);
631 atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
632 atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
633 if (phy_data & BMSR_LSTATUS) {
634 if (atl1c_get_speed_and_duplex(hw, &speed,
635 &duplex) != 0)
636 dev_dbg(&pdev->dev,
637 "get speed and duplex failed\n");
638 break;
639 }
640 }
641 }
642 } else {
643 speed = SPEED_10;
644 duplex = HALF_DUPLEX;
645 }
646 adapter->link_speed = speed;
647 adapter->link_duplex = duplex;
648
649 return ret;
650}
651
575int atl1c_restart_autoneg(struct atl1c_hw *hw) 652int atl1c_restart_autoneg(struct atl1c_hw *hw)
576{ 653{
577 int err = 0; 654 int err = 0;