diff options
author | Huang, Xiong <xiong@qca.qualcomm.com> | 2012-04-25 20:27:12 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-26 05:03:32 -0400 |
commit | 7737fd96450236accb4856916366240a96de97be (patch) | |
tree | 82cac7341900cbba2dbed1fc488de56a2346d27b /drivers/net/ethernet/atheros/atl1c/atl1c_main.c | |
parent | ce3ba0c995c194bb922fd449d72a5d006c702aec (diff) |
atl1c: refine SERDES-clock related code
bit 17/18 of reg1424 must be clear for l2cb 1.x, or it will cause
the write-reg operation fail without cable connected.
so, please do connect the cable when apply this patch to the driver
to make sure these 2bits are cleared by new driver.
The revised code is move to al1c_reset_mac.
SERDES register definition is refined as well.
when do reset MAC, speed/duplex control right should be transferred
to software before do PHY auto-neg -- by bit MASTER_CTRL_SPEED_MODE_SW.
SERDES register definition is refined as well.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/atheros/atl1c/atl1c_main.c')
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index f0f348bf6c1..cf78287d0e5 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -1008,7 +1008,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *) adapter->tpd_ring; - u32 data; /* TPD */ AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI, @@ -1052,13 +1051,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/ AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/ } - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) { - /* Power Saving for L2c_B */ - AT_READ_REG(hw, REG_SERDES_LOCK, &data); - data |= SERDES_MAC_CLK_SLOWDOWN; - data |= SERDES_PYH_CLK_SLOWDOWN; - AT_WRITE_REG(hw, REG_SERDES_LOCK, data); - } /* Load all of base address above */ AT_WRITE_REG(hw, REG_LOAD_PTR, 1); } @@ -1177,7 +1169,7 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) { struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; struct pci_dev *pdev = adapter->pdev; - u32 master_ctrl_data = 0; + u32 ctrl_data = 0; AT_WRITE_REG(hw, REG_IMR, 0); AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT); @@ -1189,10 +1181,9 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) * the current PCI configuration. The global reset bit is self- * clearing, and should clear within a microsecond. */ - AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); - master_ctrl_data |= MASTER_CTRL_OOB_DIS; - AT_WRITE_REG(hw, REG_MASTER_CTRL, - master_ctrl_data | MASTER_CTRL_SOFT_RST); + AT_READ_REG(hw, REG_MASTER_CTRL, &ctrl_data); + ctrl_data |= MASTER_CTRL_OOB_DIS; + AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data | MASTER_CTRL_SOFT_RST); AT_WRITE_FLUSH(hw); msleep(10); @@ -1204,7 +1195,28 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) " disabled for 10ms second\n"); return -1; } - AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); + AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data); + + /* driver control speed/duplex */ + AT_READ_REG(hw, REG_MAC_CTRL, &ctrl_data); + AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl_data | MAC_CTRL_SPEED_MODE_SW); + + /* clk switch setting */ + AT_READ_REG(hw, REG_SERDES, &ctrl_data); + switch (hw->nic_type) { + case athr_l2c_b: + ctrl_data &= ~(SERDES_PHY_CLK_SLOWDOWN | + SERDES_MAC_CLK_SLOWDOWN); + AT_WRITE_REG(hw, REG_SERDES, ctrl_data); + break; + case athr_l2c_b2: + case athr_l1d_2: + ctrl_data |= SERDES_PHY_CLK_SLOWDOWN | SERDES_MAC_CLK_SLOWDOWN; + AT_WRITE_REG(hw, REG_SERDES, ctrl_data); + break; + default: + break; + } return 0; } |