From: xiong <xiong@qca.qualcomm.com>
To: <davem@davemloft.net>, <netdev@vger.kernel.org>,
<linux-kernel@vger.kernel.org>
Cc: <qca-linux-team@qualcomm.com>, <nic-devel@qualcomm.com>,
xiong <xiong@qca.qualcomm.com>
Subject: [PATCH 36/37] atl1c: refine mac address related code
Date: Fri, 13 Apr 2012 08:15:01 +0800 [thread overview]
Message-ID: <1334276102-15866-37-git-send-email-xiong@qca.qualcomm.com> (raw)
In-Reply-To: <1334276102-15866-1-git-send-email-xiong@qca.qualcomm.com>
On some platform with EEPROM/OTP existing, the BIOS could overwrite
a new MAC address for the NIC. so, the permanent mac address should
be from BIOS. the address is restored when driver removing.
Voltage raising isn't applicable for l1d.
Replace swab32 with htonl for big/little endian platform.
related Registers are refined as well.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | 93 ++++++++++-------------
drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 32 +++-----
drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 6 +-
3 files changed, 57 insertions(+), 74 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 3eaf78a..97f0f7e 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -43,7 +43,7 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
return 0;
}
-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr)
{
u32 value;
/*
@@ -51,33 +51,48 @@ void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
* 0: 6AF600DC 1: 000B
* low dword
*/
- value = (((u32)hw->mac_addr[2]) << 24) |
- (((u32)hw->mac_addr[3]) << 16) |
- (((u32)hw->mac_addr[4]) << 8) |
- (((u32)hw->mac_addr[5])) ;
+ value = mac_addr[2] << 24 |
+ mac_addr[3] << 16 |
+ mac_addr[4] << 8 |
+ mac_addr[5];
AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
/* hight dword */
- value = (((u32)hw->mac_addr[0]) << 8) |
- (((u32)hw->mac_addr[1])) ;
+ value = mac_addr[0] << 8 |
+ mac_addr[1];
AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
}
+/* read mac address from hardware register */
+static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr)
+{
+ u32 addr[2];
+
+ AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
+ AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
+
+ *(u32 *) ð_addr[2] = htonl(addr[0]);
+ *(u16 *) ð_addr[0] = htons((u16)addr[1]);
+
+ return is_valid_ether_addr(eth_addr);
+}
+
/*
* atl1c_get_permanent_address
* return 0 if get valid mac address,
*/
static int atl1c_get_permanent_address(struct atl1c_hw *hw)
{
- u32 addr[2];
u32 i;
u32 otp_ctrl_data;
u32 twsi_ctrl_data;
- u8 eth_addr[ETH_ALEN];
u16 phy_data;
bool raise_vol = false;
+ /* MAC-address from BIOS is the 1st priority */
+ if (atl1c_read_current_addr(hw, hw->perm_mac_addr))
+ return 0;
+
/* init */
- addr[0] = addr[1] = 0;
AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
if (atl1c_check_eeprom_exist(hw)) {
if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) {
@@ -89,21 +104,14 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
msleep(1);
}
}
-
- if (hw->nic_type == athr_l2c_b ||
- hw->nic_type == athr_l2c_b2 ||
- hw->nic_type == athr_l1d) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data &= 0xFF7F;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data |= 0x8;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
+ /* raise voltage temporally for l2cb */
+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
+ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);
+ phy_data &= ~ANACTRL_HB_EN;
+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);
+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
+ phy_data |= VOLT_CTRL_SWLOWEST;
+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
udelay(20);
raise_vol = true;
}
@@ -127,37 +135,18 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
msleep(1);
}
if (raise_vol) {
- if (hw->nic_type == athr_l2c_b ||
- hw->nic_type == athr_l2c_b2 ||
- hw->nic_type == athr_l1d ||
- hw->nic_type == athr_l1d_2) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data |= 0x80;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data &= 0xFFF7;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
- udelay(20);
- }
+ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);
+ phy_data |= ANACTRL_HB_EN;
+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);
+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
+ phy_data &= ~VOLT_CTRL_SWLOWEST;
+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
+ udelay(20);
}
- /* maybe MAC-address is from BIOS */
- AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
- AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
- *(u32 *) ð_addr[2] = swab32(addr[0]);
- *(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]);
-
- if (is_valid_ether_addr(eth_addr)) {
- memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ if (atl1c_read_current_addr(hw, hw->perm_mac_addr))
return 0;
- }
-out:
return -1;
}
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 47b0f3d..2e6fbb9 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -36,7 +36,7 @@ struct atl1c_hw;
/* function prototype */
void atl1c_phy_disable(struct atl1c_hw *hw);
-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw);
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr);
int atl1c_phy_reset(struct atl1c_hw *hw);
int atl1c_read_mac_addr(struct atl1c_hw *hw);
int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex);
@@ -133,25 +133,17 @@ void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed);
#define REG_DEV_SERIAL_NUM_EN_SHIFT 1
#define REG_TWSI_CTRL 0x218
+#define TWSI_CTLR_FREQ_MASK 0x3UL
+#define TWSI_CTRL_FREQ_SHIFT 24
+#define TWSI_CTRL_FREQ_100K 0
+#define TWSI_CTRL_FREQ_200K 1
+#define TWSI_CTRL_FREQ_300K 2
+#define TWSI_CTRL_FREQ_400K 3
+#define TWSI_CTRL_LD_EXIST BIT(23)
+#define TWSI_CTRL_HW_LDSTAT BIT(12) /* 0:finish,1:in progress */
+#define TWSI_CTRL_SW_LDSTART BIT(11)
#define TWSI_CTRL_LD_OFFSET_MASK 0xFF
#define TWSI_CTRL_LD_OFFSET_SHIFT 0
-#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7
-#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8
-#define TWSI_CTRL_SW_LDSTART 0x800
-#define TWSI_CTRL_HW_LDSTART 0x1000
-#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F
-#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15
-#define TWSI_CTRL_LD_EXIST 0x400000
-#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3
-#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23
-#define TWSI_CTRL_FREQ_SEL_100K 0
-#define TWSI_CTRL_FREQ_SEL_200K 1
-#define TWSI_CTRL_FREQ_SEL_300K 2
-#define TWSI_CTRL_FREQ_SEL_400K 3
-#define TWSI_CTRL_SMB_SLV_ADDR
-#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3
-#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24
-
#define REG_PCIE_DEV_MISC_CTRL 0x21C
#define PCIE_DEV_MISC_EXT_PIPE 0x2
@@ -174,7 +166,7 @@ void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed);
#define L2CB1_PCIE_PHYMISC2_CDR_BW 3
#define REG_TWSI_DEBUG 0x1108
-#define TWSI_DEBUG_DEV_EXIST 0x20000000
+#define TWSI_DEBUG_DEV_EXIST BIT(29)
#define REG_DMA_DBG 0x1114
#define DMA_DBG_VENDOR_MSG BIT(0)
@@ -190,7 +182,7 @@ void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed);
#define REG_EEPROM_DATA_LO 0x12C4
#define REG_OTP_CTRL 0x12F0
-#define OTP_CTRL_CLK_EN 0x0002
+#define OTP_CTRL_CLK_EN BIT(1)
#define REG_PM_CTRL 0x12F8
#define PM_CTRL_HOTRST BIT(31)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 79dae19..4b9865b 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -457,7 +457,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
- atl1c_hw_set_mac_addr(&adapter->hw);
+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr);
return 0;
}
@@ -2536,7 +2536,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
dev_dbg(&pdev->dev, "mac address : %pM\n",
adapter->hw.mac_addr);
- atl1c_hw_set_mac_addr(&adapter->hw);
+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr);
INIT_WORK(&adapter->common_task, atl1c_common_task);
adapter->work_event = 0;
err = register_netdev(netdev);
@@ -2580,6 +2580,8 @@ static void __devexit atl1c_remove(struct pci_dev *pdev)
struct atl1c_adapter *adapter = netdev_priv(netdev);
unregister_netdev(netdev);
+ /* restore permanent address */
+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.perm_mac_addr);
atl1c_phy_disable(&adapter->hw);
iounmap(adapter->hw.hw_addr);
--
1.7.7
next prev parent reply other threads:[~2012-04-13 0:21 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-13 0:14 [PATCH 00/37] atl1c: update hardware settings xiong
2012-04-13 0:14 ` [PATCH 01/37] atl1c: update author contact info & company/driver desciption xiong
2012-04-13 0:14 ` [PATCH 02/37] atl1c: remove multiple-RX-Q code xiong
2012-04-13 0:14 ` [PATCH 03/37] atl1c: remove HDS register xiong
2012-04-13 0:14 ` [PATCH 04/37] atl1c: remove VPD register xiong
2012-04-14 0:45 ` David Miller
2012-04-14 9:12 ` Huang, Xiong
2012-04-14 14:22 ` Ben Hutchings
2012-04-14 18:24 ` David Miller
2012-04-17 8:36 ` Huang, Xiong
2012-04-13 0:14 ` [PATCH 05/37] atl1c: remove SMB/CMB DMA related code xiong
2012-04-13 0:14 ` [PATCH 06/37] atl1c: split 2 32bit registers of TPD to 4 16bit registers xiong
2012-04-13 0:14 ` [PATCH 07/37] atl1c: remove code related to rxq 1/2/3 xiong
2012-04-13 0:14 ` [PATCH 08/37] atl1c: wrong register used to stop TXQ xiong
2012-04-13 0:14 ` [PATCH 09/37] atl1c: correct wrong definition of REG_DMA_CTRL xiong
2012-04-13 0:14 ` [PATCH 10/37] atl1c: remove dmaw_block xiong
2012-04-13 0:14 ` [PATCH 11/37] atl1c: using fixed TXQ configuration for l2cb and l1c xiong
2012-04-13 0:14 ` [PATCH 12/37] atl1c: restore max-read-request-size in Device Conrol Register xiong
2012-04-13 17:02 ` Ben Hutchings
2012-04-14 10:39 ` Huang, Xiong
2012-04-13 0:14 ` [PATCH 13/37] atl1c: threshold for ASPM is changed based on chip capability xiong
2012-04-13 0:14 ` [PATCH 14/37] atl1c: add module parameter for l1c_wait_until_idle xiong
2012-04-13 0:14 ` [PATCH 15/37] atl1c: update right threshold for TSO xiong
2012-04-13 0:14 ` [PATCH 16/37] atl1c: remove dmar_dly_cnt and dmaw_dly_cnt xiong
2012-04-13 0:14 ` [PATCH 17/37] atl1c: clear PCIE error status in atl1c_reset_pcie xiong
2012-04-13 0:14 ` [PATCH 18/37] atl1c: refine reg definition of REG_MASTER_CTRL xiong
2012-04-13 0:14 ` [PATCH 19/37] atl1c: clear bit MASTER_CTRL_CLK_SEL_DIS in atl1c_pcie_patch xiong
2012-04-13 0:14 ` [PATCH 20/37] atl1c: refine/update ASPM configuration xiong
2012-04-13 0:14 ` [PATCH 21/37] atl1c: refine atl1c_pcie_patch xiong
2012-04-13 0:14 ` [PATCH 22/37] atl1c: fix WoL(magic) issue for l2cb 1.1 xiong
2012-04-13 0:14 ` [PATCH 23/37] atl1c: remove MDIO_REG_ADDR_MASK in atl1c_mdio_read/write xiong
2012-04-13 0:14 ` [PATCH 24/37] atl1c: remove REG_PHY_STATUS xiong
2012-04-13 0:14 ` [PATCH 25/37] atl1c: refine phy-register read/write function xiong
2012-04-13 0:14 ` [PATCH 26/37] atl1c: remove PHY contrl in atl1c_reset_pcie xiong
2012-04-13 0:14 ` [PATCH 27/37] atl1c: refine SERDES-clock related code xiong
2012-04-13 0:14 ` [PATCH 28/37] atl1c: remove PHY polling from atl1c_open xiong
2012-04-13 0:14 ` [PATCH 29/37] atl1c: update PHY reset related routine xiong
2012-04-13 0:14 ` [PATCH 30/37] atl1c: remove PHY reset/init for link down event xiong
2012-04-13 0:14 ` [PATCH 31/37] atl1c: add function atl1c_power_saving xiong
2012-04-13 0:14 ` [PATCH 32/37] atl1c: refine start/enable code for MAC module xiong
2012-04-13 0:14 ` [PATCH 33/37] atl1c: add PHY link event(up/down) patch xiong
2012-04-13 0:14 ` [PATCH 34/37] atl1c: clear WoL status when reset pcie xiong
2012-04-13 0:15 ` [PATCH 35/37] atl1c: remove code of closing register writable attribution xiong
2012-04-13 0:15 ` xiong [this message]
2012-04-13 0:15 ` [PATCH 37/37] atl1c: cancel task when interface closed xiong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1334276102-15866-37-git-send-email-xiong@qca.qualcomm.com \
--to=xiong@qca.qualcomm.com \
--cc=davem@davemloft.net \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=nic-devel@qualcomm.com \
--cc=qca-linux-team@qualcomm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®