All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] atl1c: update hardware settings - v3
@ 2012-04-20  6:16 xiong
  2012-04-20  6:16 ` [PATCH 1/9] atl1c: remove REG_PHY_STATUS xiong
                   ` (9 more replies)
  0 siblings, 10 replies; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

This update contains a serial of patches, most of them are hardware
settings related. register definitions are refined (or removed if
meaningless) for each patch.

This is the third serial patches, after reviewed/applied the fourth
serial will be out.

The patches have addressed all sparse and checkpatch warnings.

Following NICs are tested:
AR8131/AR8132/AR8151A/AR8152A/AR8152B
Test item includes:
build/install/uninstall/dhcp/ping/iperf/wol/reboot/etc.

xiong (9):
  atl1c: remove REG_PHY_STATUS
  atl1c: refine phy-register read/write function
  atl1c: remove PHY contrl in atl1c_reset_pcie
  atl1c: refine SERDES-clock related code
  atl1c: remove PHY polling from atl1c_open
  atl1c: update PHY reset related routine
  atl1c: remove PHY reset/init for link down event
  atl1c: add function atl1c_power_saving
  atl1c: refine start/enable code for MAC module

 drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c |    2 +-
 drivers/net/ethernet/atheros/atl1c/atl1c_hw.c      |  422 ++++++++++++-----
 drivers/net/ethernet/atheros/atl1c/atl1c_hw.h      |  499 +++++++++++++-------
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c    |  240 +++-------
 4 files changed, 693 insertions(+), 470 deletions(-)

-- 
1.7.7


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/9] atl1c: remove REG_PHY_STATUS
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
@ 2012-04-20  6:16 ` xiong
  2012-04-20  6:16 ` [PATCH 2/9] atl1c: refine phy-register read/write function xiong
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

this register is used for l1e(dev=1026)
l1c/l1d/l2cb don't use it.

Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
 drivers/net/ethernet/atheros/atl1c/atl1c_hw.h   |    7 -------
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    2 --
 2 files changed, 0 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index cc7afa1..459e141 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -293,13 +293,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
 #define MDIO_AP_EN              	0x10000000
 #define MDIO_WAIT_TIMES         	10
 
-/* MII PHY Status Register */
-#define REG_PHY_STATUS           	0x1418
-#define PHY_GENERAL_STATUS_MASK		0xFFFF
-#define PHY_STATUS_RECV_ENABLE		0x0001
-#define PHY_OE_PWSP_STATUS_MASK		0x07FF
-#define PHY_OE_PWSP_STATUS_SHIFT	16
-#define PHY_STATUS_LPW_STATE		0x80000000
 /* BIST Control and Status Register0 (for the Packet Memory) */
 #define REG_BIST0_CTRL              	0x141c
 #define BIST0_NOW                   	0x1
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index df10637..a6c3f05 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -699,11 +699,9 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw)
 
 static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
 {
-	u32 phy_status_data;
 	u32 link_ctrl_data;
 
 	atl1c_set_mac_type(hw);
-	AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data);
 	AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
 
 	hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE  |
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/9] atl1c: refine phy-register read/write function
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
  2012-04-20  6:16 ` [PATCH 1/9] atl1c: remove REG_PHY_STATUS xiong
@ 2012-04-20  6:16 ` xiong
  2012-04-20  7:40   ` Florian Fainelli
  2012-04-20  6:16 ` [PATCH 3/9] atl1c: remove PHY contrl in atl1c_reset_pcie xiong
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

phy register is read/write via MDIO control module ---
that module will be affected by the hibernate status,
to access phy regs in hib stutus, slow frequency clk must
be selected.
To access phy extension register, the MDIO related
registers are refined/updated, a _core function is
re-wroted for both regular PHY regs and extension regs.
existing PHY r/w function is revised based on the _core.
PHY extension registers will be used for the comming
patches.

Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
 drivers/net/ethernet/atheros/atl1c/atl1c_hw.c   |  178 +++++++++++++++++++----
 drivers/net/ethernet/atheros/atl1c/atl1c_hw.h   |   64 +++++---
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    4 +-
 3 files changed, 189 insertions(+), 57 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index bd1667c..6cbe78a 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -277,65 +277,181 @@ void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
 	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
 }
 
+
+void atl1c_stop_phy_polling(struct atl1c_hw *hw)
+{
+	u32 val;
+	int i;
+
+	if (hw->ctrl_flags & ATL1C_FPGA_VERSION) {
+		AT_WRITE_REG(hw, REG_MDIO_CTRL, 0);
+		for (i = 0; i < MDIO_MAX_AC_TO; i++) {
+			AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+			if (0 == (val & MDIO_CTRL_BUSY))
+				break;
+			udelay(10);
+		}
+	}
+}
+
+void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel)
+{
+	u32 val;
+	int i;
+
+	if (hw->ctrl_flags & ATL1C_FPGA_VERSION) {
+		val = MDIO_CTRL_SPRES_PRMBL |
+			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+			FIELDX(MDIO_CTRL_REG, 1) |
+			MDIO_CTRL_START |
+			MDIO_CTRL_OP_READ;
+		AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+		for (i = 0; i < MDIO_MAX_AC_TO; i++) {
+			AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+			if (0 == (val & MDIO_CTRL_BUSY))
+				break;
+			udelay(10);
+		}
+		val |= MDIO_CTRL_AP_EN;
+		val &= ~MDIO_CTRL_START;
+		AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+		udelay(30);
+	}
+}
+
+
 /*
- * Reads the value from a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to read
+ * atl1c_read_phy_core
+ * core funtion to read register in PHY via MDIO control regsiter.
+ * ext: extension register (see IEEE 802.3)
+ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
+ * reg: reg to read
  */
-int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
+int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
+			u16 reg, u16 *phy_data)
 {
 	u32 val;
+	u16 clk_sel;
 	int i;
 
-	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
-		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
-		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+	atl1c_stop_phy_polling(hw);
 
+	*phy_data = 0;
+	clk_sel = hw->hibernate ? MDIO_CTRL_CLK_25_128 : MDIO_CTRL_CLK_25_4;
+	if (ext) {
+		val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
+		AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
+		val = MDIO_CTRL_SPRES_PRMBL |
+			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+			MDIO_CTRL_START |
+			MDIO_CTRL_MODE_EXT |
+			MDIO_CTRL_OP_READ;
+	} else {
+		val = MDIO_CTRL_SPRES_PRMBL |
+			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+			FIELDX(MDIO_CTRL_REG, reg) |
+			MDIO_CTRL_START |
+			MDIO_CTRL_OP_READ;
+	}
 	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
 
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
+	for (i = 0; i < MDIO_MAX_AC_TO; i++) {
 		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
+		if (0 == (val & MDIO_CTRL_BUSY)) {
+			*phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA);
 			break;
+		}
+		udelay(10);
 	}
-	if (!(val & (MDIO_START | MDIO_BUSY))) {
-		*phy_data = (u16)val;
-		return 0;
-	}
+	if (MDIO_MAX_AC_TO == i)
+		return -1;
 
-	return -1;
+	atl1c_start_phy_polling(hw, clk_sel);
+
+	return 0;
 }
 
 /*
- * Writes a value to a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to write
- * data - data to write to the PHY
+ * atl1c_write_phy_core
+ * core funtion to write to register in PHY via MDIO control regsiter.
+ * ext: extension register (see IEEE 802.3)
+ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
+ * reg: reg to write
  */
-int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
+int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
+			u16 reg, u16 phy_data)
 {
-	int i;
 	u32 val;
+	u16 clk_sel;
+	int i;
 
-	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT   |
-	       (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
-	       MDIO_SUP_PREAMBLE | MDIO_START |
-	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+	atl1c_stop_phy_polling(hw);
 
+	clk_sel = hw->hibernate ? MDIO_CTRL_CLK_25_128 : MDIO_CTRL_CLK_25_4;
+	if (ext) {
+		val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
+		AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
+		val = MDIO_CTRL_SPRES_PRMBL |
+			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+			FIELDX(MDIO_CTRL_DATA, phy_data) |
+			MDIO_CTRL_START |
+			MDIO_CTRL_MODE_EXT;
+	} else {
+		val = MDIO_CTRL_SPRES_PRMBL |
+			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+			FIELDX(MDIO_CTRL_DATA, phy_data) |
+			FIELDX(MDIO_CTRL_REG, reg) |
+			MDIO_CTRL_START;
+	}
 	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
 
-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
-		udelay(2);
+	for (i = 0; i < MDIO_MAX_AC_TO; i++) {
 		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
-		if (!(val & (MDIO_START | MDIO_BUSY)))
+		if (0 == (val & MDIO_CTRL_BUSY))
 			break;
+		udelay(10);
 	}
+	if (MDIO_MAX_AC_TO == i)
+		return -1;
 
-	if (!(val & (MDIO_START | MDIO_BUSY)))
-		return 0;
+	atl1c_start_phy_polling(hw, clk_sel);
 
-	return -1;
+	return 0;
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+	return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data);
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
+{
+	return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data);
+}
+
+/* read from PHY extension register */
+int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
+			u16 reg_addr, u16 *phy_data)
+{
+	return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data);
+}
+
+/* write to PHY extension register */
+int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
+			u16 reg_addr, u16 phy_data)
+{
+	return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data);
 }
 
 /*
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 459e141..eb7f3bb 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -49,6 +49,16 @@ int atl1c_phy_init(struct atl1c_hw *hw);
 int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
 int atl1c_restart_autoneg(struct atl1c_hw *hw);
 int atl1c_phy_power_saving(struct atl1c_hw *hw);
+void atl1c_stop_phy_polling(struct atl1c_hw *hw);
+void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel);
+int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
+			u16 reg, u16 *phy_data);
+int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
+			u16 reg, u16 phy_data);
+int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
+			u16 reg_addr, u16 *phy_data);
+int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
+			u16 reg_addr, u16 phy_data);
 /* register definition */
 #define REG_DEVICE_CAP              	0x5C
 #define DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
@@ -268,30 +278,36 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
 
 /* MDIO Control Register */
 #define REG_MDIO_CTRL           	0x1414
-#define MDIO_DATA_MASK          	0xffff  /* On MDIO write, the 16-bit
-						 * control data to write to PHY
-						 * MII management register */
-#define MDIO_DATA_SHIFT         	0       /* On MDIO read, the 16-bit
-						 * status data that was read
-						 * from the PHY MII management register */
-#define MDIO_REG_ADDR_MASK      	0x1f    /* MDIO register address */
-#define MDIO_REG_ADDR_SHIFT     	16
-#define MDIO_RW                 	0x200000  /* 1: read, 0: write */
-#define MDIO_SUP_PREAMBLE       	0x400000  /* Suppress preamble */
-#define MDIO_START              	0x800000  /* Write 1 to initiate the MDIO
-						   * master. And this bit is self
-						   * cleared after one cycle */
-#define MDIO_CLK_SEL_SHIFT      	24
-#define MDIO_CLK_25_4           	0
-#define MDIO_CLK_25_6           	2
-#define MDIO_CLK_25_8           	3
-#define MDIO_CLK_25_10          	4
-#define MDIO_CLK_25_14          	5
-#define MDIO_CLK_25_20          	6
-#define MDIO_CLK_25_28          	7
-#define MDIO_BUSY               	0x8000000
-#define MDIO_AP_EN              	0x10000000
-#define MDIO_WAIT_TIMES         	10
+#define MDIO_CTRL_MODE_EXT		BIT(30)
+#define MDIO_CTRL_POST_READ		BIT(29)
+#define MDIO_CTRL_AP_EN			BIT(28)
+#define MDIO_CTRL_BUSY			BIT(27)
+#define MDIO_CTRL_CLK_SEL_MASK		0x7UL
+#define MDIO_CTRL_CLK_SEL_SHIFT		24
+#define MDIO_CTRL_CLK_25_4		0	/* 25MHz divide 4 */
+#define MDIO_CTRL_CLK_25_6		2
+#define MDIO_CTRL_CLK_25_8		3
+#define MDIO_CTRL_CLK_25_10		4
+#define MDIO_CTRL_CLK_25_32		5
+#define MDIO_CTRL_CLK_25_64		6
+#define MDIO_CTRL_CLK_25_128		7
+#define MDIO_CTRL_START			BIT(23)
+#define MDIO_CTRL_SPRES_PRMBL		BIT(22)
+#define MDIO_CTRL_OP_READ		BIT(21)	/* 1:read, 0:write */
+#define MDIO_CTRL_REG_MASK		0x1FUL
+#define MDIO_CTRL_REG_SHIFT		16
+#define MDIO_CTRL_DATA_MASK		0xFFFFUL
+#define MDIO_CTRL_DATA_SHIFT		0
+#define MDIO_MAX_AC_TO			120	/* 1.2ms timeout for slow clk */
+
+/* for extension reg access */
+#define REG_MDIO_EXTN			0x1448
+#define MDIO_EXTN_PORTAD_MASK		0x1FUL
+#define MDIO_EXTN_PORTAD_SHIFT		21
+#define MDIO_EXTN_DEVAD_MASK		0x1FUL
+#define MDIO_EXTN_DEVAD_SHIFT		16
+#define MDIO_EXTN_REG_MASK		0xFFFFUL
+#define MDIO_EXTN_REG_SHIFT		0
 
 /* BIST Control and Status Register0 (for the Packet Memory) */
 #define REG_BIST0_CTRL              	0x141c
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index a6c3f05..1f82880 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2270,7 +2270,7 @@ static int atl1c_open(struct net_device *netdev)
 		u32 phy_data;
 
 		AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data);
-		phy_data |= MDIO_AP_EN;
+		phy_data |= MDIO_CTRL_AP_EN;
 		AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data);
 	}
 	return 0;
@@ -2558,7 +2558,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
 	adapter->mii.mdio_read  = atl1c_mdio_read;
 	adapter->mii.mdio_write = atl1c_mdio_write;
 	adapter->mii.phy_id_mask = 0x1f;
-	adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+	adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK;
 	netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64);
 	setup_timer(&adapter->phy_config_timer, atl1c_phy_config,
 			(unsigned long)adapter);
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/9] atl1c: remove PHY contrl in atl1c_reset_pcie
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
  2012-04-20  6:16 ` [PATCH 1/9] atl1c: remove REG_PHY_STATUS xiong
  2012-04-20  6:16 ` [PATCH 2/9] atl1c: refine phy-register read/write function xiong
@ 2012-04-20  6:16 ` xiong
  2012-04-20  6:16 ` [PATCH 4/9] atl1c: refine SERDES-clock related code xiong
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

atl1c_reset_phy follows atl1c_reset_pcie in the whole driver,
so, it's unnecessary to add PHY control code in atl1c_reset_pcie.

Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 1f82880..f0f348b 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -165,11 +165,6 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
 	atl1c_pcie_patch(hw);
 	if (flag & ATL1C_PCIE_L0S_L1_DISABLE)
 		atl1c_disable_l0s_l1(hw);
-	if (flag & ATL1C_PCIE_PHY_RESET)
-		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
-	else
-		AT_WRITE_REG(hw, REG_GPHY_CTRL,
-			GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET);
 
 	msleep(5);
 }
@@ -2409,8 +2404,7 @@ static int atl1c_resume(struct device *dev)
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 
 	AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
-	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
-			ATL1C_PCIE_PHY_RESET);
+	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE);
 
 	atl1c_phy_reset(&adapter->hw);
 	atl1c_reset_mac(&adapter->hw);
@@ -2568,8 +2562,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
 		dev_err(&pdev->dev, "net device private data init failed\n");
 		goto err_sw_init;
 	}
-	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
-			ATL1C_PCIE_PHY_RESET);
+	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE);
 
 	/* Init GPHY as early as possible due to power saving issue  */
 	atl1c_phy_reset(&adapter->hw);
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/9] atl1c: refine SERDES-clock related code
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
                   ` (2 preceding siblings ...)
  2012-04-20  6:16 ` [PATCH 3/9] atl1c: remove PHY contrl in atl1c_reset_pcie xiong
@ 2012-04-20  6:16 ` xiong
  2012-04-20  6:16 ` [PATCH 5/9] atl1c: remove PHY polling from atl1c_open xiong
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

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>
---
 drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c |    2 +-
 drivers/net/ethernet/atheros/atl1c/atl1c_hw.h      |   34 +++++++++++------
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c    |   40 +++++++++++++-------
 3 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
index 3feb846..859ea84 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
@@ -153,7 +153,7 @@ static void atl1c_get_regs(struct net_device *netdev,
 	AT_READ_REG(hw, REG_LINK_CTRL, 		  p++);
 	AT_READ_REG(hw, REG_IDLE_STATUS, 	  p++);
 	AT_READ_REG(hw, REG_MDIO_CTRL, 		  p++);
-	AT_READ_REG(hw, REG_SERDES_LOCK, 	  p++);
+	AT_READ_REG(hw, REG_SERDES,		  p++);
 	AT_READ_REG(hw, REG_MAC_CTRL, 		  p++);
 	AT_READ_REG(hw, REG_MAC_IPG_IFG, 	  p++);
 	AT_READ_REG(hw, REG_MAC_STA_ADDR, 	  p++);
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index eb7f3bb..7be6f5d 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -326,18 +326,28 @@ int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
 #define BIST1_FUSE_FLAG             	0x4
 
 /* SerDes Lock Detect Control and Status Register */
-#define REG_SERDES_LOCK            	0x1424
-#define SERDES_LOCK_DETECT          	0x1  /* SerDes lock detected. This signal
-					      * comes from Analog SerDes */
-#define SERDES_LOCK_DETECT_EN       	0x2  /* 1: Enable SerDes Lock detect function */
-#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE
-#define SERDES_LOCK_STS_SELFB_PLL_MASK  0x3
-#define SERDES_OVCLK_18_25		0x0
-#define SERDES_OVCLK_12_18		0x1
-#define SERDES_OVCLK_0_4		0x2
-#define SERDES_OVCLK_4_12		0x3
-#define SERDES_MAC_CLK_SLOWDOWN		0x20000
-#define SERDES_PYH_CLK_SLOWDOWN		0x40000
+#define REG_SERDES			0x1424
+#define SERDES_PHY_CLK_SLOWDOWN		BIT(18)
+#define SERDES_MAC_CLK_SLOWDOWN		BIT(17)
+#define SERDES_SELFB_PLL_MASK		0x3UL
+#define SERDES_SELFB_PLL_SHIFT		14
+#define SERDES_PHYCLK_SEL_GTX		BIT(13)	/* 1:gtx_clk, 0:25M */
+#define SERDES_PCIECLK_SEL_SRDS		BIT(12)	/* 1:serdes,0:25M */
+#define SERDES_BUFS_RX_EN		BIT(11)
+#define SERDES_PD_RX			BIT(10)
+#define SERDES_PLL_EN			BIT(9)
+#define SERDES_EN			BIT(8)
+#define SERDES_SELFB_PLL_SEL_CSR	BIT(6)	/* 0:state-machine,1:csr */
+#define SERDES_SELFB_PLL_CSR_MASK	0x3UL
+#define SERDES_SELFB_PLL_CSR_SHIFT	4
+#define SERDES_SELFB_PLL_CSR_4		3	/* 4-12% OV-CLK */
+#define SERDES_SELFB_PLL_CSR_0		2	/* 0-4% OV-CLK */
+#define SERDES_SELFB_PLL_CSR_12		1	/* 12-18% OV-CLK */
+#define SERDES_SELFB_PLL_CSR_18		0	/* 18-25% OV-CLK */
+#define SERDES_VCO_SLOW			BIT(3)
+#define SERDES_VCO_FAST			BIT(2)
+#define SERDES_LOCK_DETECT_EN		BIT(1)
+#define SERDES_LOCK_DETECT		BIT(0)
 
 /* MAC Control Register  */
 #define REG_MAC_CTRL         		0x1480
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index f0f348b..cf78287 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;
 }
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/9] atl1c: remove PHY polling from atl1c_open
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
                   ` (3 preceding siblings ...)
  2012-04-20  6:16 ` [PATCH 4/9] atl1c: refine SERDES-clock related code xiong
@ 2012-04-20  6:16 ` xiong
  2012-04-20  6:16 ` [PATCH 6/9] atl1c: update PHY reset related routine xiong
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

PHY polling code for FPGA is considered in every MDIO R/W API.
no need to add additional code to atl1c_open.

Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index cf78287..8a1d2f9 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2273,13 +2273,6 @@ static int atl1c_open(struct net_device *netdev)
 	if (unlikely(err))
 		goto err_up;
 
-	if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
-		u32 phy_data;
-
-		AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data);
-		phy_data |= MDIO_CTRL_AP_EN;
-		AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data);
-	}
 	return 0;
 
 err_up:
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/9] atl1c: update PHY reset related routine
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
                   ` (4 preceding siblings ...)
  2012-04-20  6:16 ` [PATCH 5/9] atl1c: remove PHY polling from atl1c_open xiong
@ 2012-04-20  6:16 ` xiong
  2012-04-20  6:16 ` [PATCH 7/9] atl1c: remove PHY reset/init for link down event xiong
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

Many magic data are re-configured for PHY during its reset operation
based on chip type to get better compability and stability.
REG_PHY_CTRL register may be configured by BIOS before enter OS.
so, the driver can't directly write to it without any Read-Op.
this change also affect suspend and phy_disable routines.
PHY debug ports and extension 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   |  188 +++++++------
 drivers/net/ethernet/atheros/atl1c/atl1c_hw.h   |  323 ++++++++++++++++-------
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |   23 +-
 3 files changed, 340 insertions(+), 194 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 6cbe78a..7172d61 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -454,6 +454,32 @@ int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
 	return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data);
 }
 
+int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+	int err;
+
+	err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr);
+	if (unlikely(err))
+		return err;
+	else
+		err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data);
+
+	return err;
+}
+
+int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data)
+{
+	int err;
+
+	err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr);
+	if (unlikely(err))
+		return err;
+	else
+		err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
+
+	return err;
+}
+
 /*
  * Configures PHY autoneg and flow control advertisement settings
  *
@@ -496,119 +522,107 @@ static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
 
 void atl1c_phy_disable(struct atl1c_hw *hw)
 {
-	AT_WRITE_REGW(hw, REG_GPHY_CTRL,
-			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
-}
-
-static void atl1c_phy_magic_data(struct atl1c_hw *hw)
-{
-	u16 data;
+	u32 phy_ctrl_data;
 
-	data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
-		((1 & ANA_INTERVAL_SEL_TIMER_MASK) <<
-		ANA_INTERVAL_SEL_TIMER_SHIFT);
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG |
-		ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL |
-		ANA_SERDES_EN_LCKDT;
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	data = (44 & ANA_LONG_CABLE_TH_100_MASK) |
-		((33 & ANA_SHORT_CABLE_TH_100_MASK) <<
-		ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM |
-		ANA_BP_SMALL_BW;
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) <<
-		ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
-		ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
-		ANA_IECHO_ADJ_0_SHIFT);
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) <<
-		ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE |
-		ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M;
-
-	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0);
-	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-	if (hw->ctrl_flags & ATL1C_HIB_DISABLE) {
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41);
-		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
-			return;
-		data &= ~ANA_TOP_PS_EN;
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11);
-		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
-			return;
-		data &= ~ANA_PS_HIB_EN;
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-	}
+	AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);
+	phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
+	phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
+			GPHY_CTRL_HIB_EN | GPHY_CTRL_PHY_IDDQ |
+			GPHY_CTRL_PWDOWN_HW;
+	AT_WRITE_REGW(hw, REG_GPHY_CTRL, phy_ctrl_data);
 }
 
+
 int atl1c_phy_reset(struct atl1c_hw *hw)
 {
 	struct atl1c_adapter *adapter = hw->adapter;
 	struct pci_dev *pdev = adapter->pdev;
 	u16 phy_data;
-	u32 phy_ctrl_data = GPHY_CTRL_DEFAULT;
-	u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN;
+	u32 phy_ctrl_data, lpi_ctrl;
 	int err;
 
-	if (hw->ctrl_flags & ATL1C_HIB_DISABLE)
-		phy_ctrl_data &= ~GPHY_CTRL_HIB_EN;
-
+	/* reset PHY core */
+	AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);
+	phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ |
+		GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS);
+	phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST;
+	if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE))
+		phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE);
+	else
+		phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE);
 	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
 	AT_WRITE_FLUSH(hw);
-	msleep(40);
-	phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
-	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
+	udelay(10);
+	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET);
 	AT_WRITE_FLUSH(hw);
-	msleep(10);
+	udelay(10 * GPHY_CTRL_EXT_RST_TO);	/* delay 800us */
 
+	/* switch clock */
 	if (hw->nic_type == athr_l2c_b) {
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x0A);
-		atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xDFFF);
+		atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data);
+		atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD,
+			phy_data & ~CFGLPSPD_RSTCNT_CLK125SW);
 	}
 
-	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, 0x3B);
-		atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7);
-		msleep(20);
+	/* tx-half amplitude issue fix */
+	if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
+		atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data);
+		phy_data |= CABLE1TH_DET_EN;
+		atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data);
 	}
-	if (hw->nic_type == athr_l1d) {
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D);
+
+	/* clear bit3 of dbgport 3B to lower voltage */
+	if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) {
+		if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
+			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);
+		}
+		/* power saving config */
+		phy_data =
+			hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ?
+			L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF;
+		atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data);
+		/* hib */
+		atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,
+			SYSMODCTRL_IECHOADJ_DEF);
+	} else {
+		/* disable pws */
+		atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data);
+		atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS,
+			phy_data & ~LEGCYPS_EN);
+		/* disable hibernate */
+		atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data);
+		atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG,
+			phy_data & HIBNEG_PSHIB_EN);
 	}
-	if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2
-		|| hw->nic_type == athr_l2c) {
-		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
-		atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
+	/* disable AZ(EEE) by default */
+	if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ||
+	    hw->nic_type == athr_l2c_b2) {
+		AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl);
+		AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN);
+		atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0);
+		atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3,
+			L2CB_CLDCTRL3);
 	}
-	err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
+
+	/* other debug port to set */
+	atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF);
+	atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF);
+	atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF);
+	/* UNH-IOL test issue, set bit7 */
+	atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG,
+		TST100BTCFG_DEF | TST100BTCFG_LITCH_EN);
+
+	/* set phy interrupt mask */
+	phy_data = IER_LINK_UP | IER_LINK_DOWN;
+	err = atl1c_write_phy_reg(hw, MII_IER, phy_data);
 	if (err) {
 		if (netif_msg_hw(adapter))
 			dev_err(&pdev->dev,
 				"Error enable PHY linkChange Interrupt\n");
 		return err;
 	}
-	if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
-		atl1c_phy_magic_data(hw);
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 7be6f5d..7251d11 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -59,6 +59,9 @@ int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
 			u16 reg_addr, u16 *phy_data);
 int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
 			u16 reg_addr, u16 phy_data);
+int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
+int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data);
+
 /* register definition */
 #define REG_DEVICE_CAP              	0x5C
 #define DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
@@ -221,41 +224,32 @@ int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
 #define IRQ_MODRT_RX_TIMER_SHIFT	16
 
 #define REG_GPHY_CTRL               	0x140C
-#define GPHY_CTRL_EXT_RESET         	0x1
-#define GPHY_CTRL_RTL_MODE		0x2
-#define GPHY_CTRL_LED_MODE		0x4
-#define GPHY_CTRL_ANEG_NOW		0x8
-#define GPHY_CTRL_REV_ANEG		0x10
-#define GPHY_CTRL_GATE_25M_EN       	0x20
-#define GPHY_CTRL_LPW_EXIT          	0x40
-#define GPHY_CTRL_PHY_IDDQ          	0x80
-#define GPHY_CTRL_PHY_IDDQ_DIS      	0x100
-#define GPHY_CTRL_GIGA_DIS		0x200
-#define GPHY_CTRL_HIB_EN            	0x400
-#define GPHY_CTRL_HIB_PULSE         	0x800
-#define GPHY_CTRL_SEL_ANA_RST       	0x1000
-#define GPHY_CTRL_PHY_PLL_ON        	0x2000
-#define GPHY_CTRL_PWDOWN_HW		0x4000
-#define GPHY_CTRL_PHY_PLL_BYPASS	0x8000
-
-#define GPHY_CTRL_DEFAULT (		 \
-		GPHY_CTRL_SEL_ANA_RST	|\
-		GPHY_CTRL_HIB_PULSE	|\
-		GPHY_CTRL_HIB_EN)
-
-#define GPHY_CTRL_PW_WOL_DIS (		 \
-		GPHY_CTRL_SEL_ANA_RST	|\
-		GPHY_CTRL_HIB_PULSE	|\
-		GPHY_CTRL_HIB_EN	|\
-		GPHY_CTRL_PWDOWN_HW	|\
-		GPHY_CTRL_PHY_IDDQ)
-
-#define GPHY_CTRL_POWER_SAVING (	\
-		GPHY_CTRL_SEL_ANA_RST	|\
-		GPHY_CTRL_HIB_EN	|\
-		GPHY_CTRL_HIB_PULSE	|\
-		GPHY_CTRL_PWDOWN_HW	|\
-		GPHY_CTRL_PHY_IDDQ)
+#define GPHY_CTRL_ADDR_MASK		0x1FUL
+#define GPHY_CTRL_ADDR_SHIFT		19
+#define GPHY_CTRL_BP_VLTGSW		BIT(18)
+#define GPHY_CTRL_100AB_EN		BIT(17)
+#define GPHY_CTRL_10AB_EN		BIT(16)
+#define GPHY_CTRL_PHY_PLL_BYPASS	BIT(15)
+#define GPHY_CTRL_PWDOWN_HW		BIT(14)	/* affect MAC&PHY, to low pw */
+#define GPHY_CTRL_PHY_PLL_ON		BIT(13)	/* 1:pll always on, 0:can sw */
+#define GPHY_CTRL_SEL_ANA_RST		BIT(12)
+#define GPHY_CTRL_HIB_PULSE		BIT(11)
+#define GPHY_CTRL_HIB_EN		BIT(10)
+#define GPHY_CTRL_GIGA_DIS		BIT(9)
+#define GPHY_CTRL_PHY_IDDQ_DIS		BIT(8)	/* pw on RST */
+#define GPHY_CTRL_PHY_IDDQ		BIT(7)	/* bit8 affect bit7 while rb */
+#define GPHY_CTRL_LPW_EXIT		BIT(6)
+#define GPHY_CTRL_GATE_25M_EN		BIT(5)
+#define GPHY_CTRL_REV_ANEG		BIT(4)
+#define GPHY_CTRL_ANEG_NOW		BIT(3)
+#define GPHY_CTRL_LED_MODE		BIT(2)
+#define GPHY_CTRL_RTL_MODE		BIT(1)
+#define GPHY_CTRL_EXT_RESET		BIT(0)	/* 1:out of DSP RST status */
+#define GPHY_CTRL_EXT_RST_TO		80	/* 800us atmost */
+#define GPHY_CTRL_CLS			(\
+	GPHY_CTRL_LED_MODE		|\
+	GPHY_CTRL_100AB_EN		|\
+	GPHY_CTRL_PHY_PLL_ON)
 
 /* Block IDLE Status Register */
 #define REG_IDLE_STATUS			0x1410
@@ -349,6 +343,26 @@ int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
 #define SERDES_LOCK_DETECT_EN		BIT(1)
 #define SERDES_LOCK_DETECT		BIT(0)
 
+#define REG_LPI_DECISN_TIMER            0x143C
+#define L2CB_LPI_DESISN_TIMER		0x7D00
+
+#define REG_LPI_CTRL                    0x1440
+#define LPI_CTRL_CHK_DA			BIT(31)
+#define LPI_CTRL_ENH_TO_MASK		0x1FFFUL
+#define LPI_CTRL_ENH_TO_SHIFT		12
+#define LPI_CTRL_ENH_TH_MASK		0x1FUL
+#define LPI_CTRL_ENH_TH_SHIFT		6
+#define LPI_CTRL_ENH_EN			BIT(5)
+#define LPI_CTRL_CHK_RX			BIT(4)
+#define LPI_CTRL_CHK_STATE		BIT(3)
+#define LPI_CTRL_GMII			BIT(2)
+#define LPI_CTRL_TO_PHY			BIT(1)
+#define LPI_CTRL_EN			BIT(0)
+
+#define REG_LPI_WAIT			0x1444
+#define LPI_WAIT_TIMER_MASK		0xFFFFUL
+#define LPI_WAIT_TIMER_SHIFT		0
+
 /* MAC Control Register  */
 #define REG_MAC_CTRL         		0x1480
 #define MAC_CTRL_TX_EN			0x1
@@ -812,73 +826,188 @@ int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
 #define MII_DBG_ADDR			0x1D
 #define MII_DBG_DATA			0x1E
 
-#define MII_ANA_CTRL_0			0x0
-#define ANA_RESTART_CAL			0x0001
-#define ANA_MANUL_SWICH_ON_SHIFT	0x1
-#define ANA_MANUL_SWICH_ON_MASK		0xF
-#define ANA_MAN_ENABLE			0x0020
-#define ANA_SEL_HSP			0x0040
-#define ANA_EN_HB			0x0080
-#define ANA_EN_HBIAS			0x0100
-#define ANA_OEN_125M			0x0200
-#define ANA_EN_LCKDT			0x0400
-#define ANA_LCKDT_PHY			0x0800
-#define ANA_AFE_MODE			0x1000
-#define ANA_VCO_SLOW			0x2000
-#define ANA_VCO_FAST			0x4000
-#define ANA_SEL_CLK125M_DSP		0x8000
+/***************************** debug port *************************************/
+
+#define MIIDBG_ANACTRL                  0x00
+#define ANACTRL_CLK125M_DELAY_EN        0x8000
+#define ANACTRL_VCO_FAST                0x4000
+#define ANACTRL_VCO_SLOW                0x2000
+#define ANACTRL_AFE_MODE_EN             0x1000
+#define ANACTRL_LCKDET_PHY              0x800
+#define ANACTRL_LCKDET_EN               0x400
+#define ANACTRL_OEN_125M                0x200
+#define ANACTRL_HBIAS_EN                0x100
+#define ANACTRL_HB_EN                   0x80
+#define ANACTRL_SEL_HSP                 0x40
+#define ANACTRL_CLASSA_EN               0x20
+#define ANACTRL_MANUSWON_SWR_MASK       3U
+#define ANACTRL_MANUSWON_SWR_SHIFT      2
+#define ANACTRL_MANUSWON_SWR_2V         0
+#define ANACTRL_MANUSWON_SWR_1P9V       1
+#define ANACTRL_MANUSWON_SWR_1P8V       2
+#define ANACTRL_MANUSWON_SWR_1P7V       3
+#define ANACTRL_MANUSWON_BW3_4M         0x2
+#define ANACTRL_RESTART_CAL             0x1
+#define ANACTRL_DEF                     0x02EF
+
+#define MIIDBG_SYSMODCTRL               0x04
+#define SYSMODCTRL_IECHOADJ_PFMH_PHY    0x8000
+#define SYSMODCTRL_IECHOADJ_BIASGEN     0x4000
+#define SYSMODCTRL_IECHOADJ_PFML_PHY    0x2000
+#define SYSMODCTRL_IECHOADJ_PS_MASK     3U
+#define SYSMODCTRL_IECHOADJ_PS_SHIFT    10
+#define SYSMODCTRL_IECHOADJ_PS_40       3
+#define SYSMODCTRL_IECHOADJ_PS_20       2
+#define SYSMODCTRL_IECHOADJ_PS_0        1
+#define SYSMODCTRL_IECHOADJ_10BT_100MV  0x40 /* 1:100mv, 0:200mv */
+#define SYSMODCTRL_IECHOADJ_HLFAP_MASK  3U
+#define SYSMODCTRL_IECHOADJ_HLFAP_SHIFT 4
+#define SYSMODCTRL_IECHOADJ_VDFULBW     0x8
+#define SYSMODCTRL_IECHOADJ_VDBIASHLF   0x4
+#define SYSMODCTRL_IECHOADJ_VDAMPHLF    0x2
+#define SYSMODCTRL_IECHOADJ_VDLANSW     0x1
+#define SYSMODCTRL_IECHOADJ_DEF         0x88BB /* ???? */
+
+/* for l1d & l2cb */
+#define SYSMODCTRL_IECHOADJ_CUR_ADD     0x8000
+#define SYSMODCTRL_IECHOADJ_CUR_MASK    7U
+#define SYSMODCTRL_IECHOADJ_CUR_SHIFT   12
+#define SYSMODCTRL_IECHOADJ_VOL_MASK    0xFU
+#define SYSMODCTRL_IECHOADJ_VOL_SHIFT   8
+#define SYSMODCTRL_IECHOADJ_VOL_17ALL   3
+#define SYSMODCTRL_IECHOADJ_VOL_100M15  1
+#define SYSMODCTRL_IECHOADJ_VOL_10M17   0
+#define SYSMODCTRL_IECHOADJ_BIAS1_MASK  0xFU
+#define SYSMODCTRL_IECHOADJ_BIAS1_SHIFT 4
+#define SYSMODCTRL_IECHOADJ_BIAS2_MASK  0xFU
+#define SYSMODCTRL_IECHOADJ_BIAS2_SHIFT 0
+#define L1D_SYSMODCTRL_IECHOADJ_DEF     0x4FBB
+
+#define MIIDBG_SRDSYSMOD                0x05
+#define SRDSYSMOD_LCKDET_EN             0x2000
+#define SRDSYSMOD_PLL_EN                0x800
+#define SRDSYSMOD_SEL_HSP               0x400
+#define SRDSYSMOD_HLFTXDR               0x200
+#define SRDSYSMOD_TXCLK_DELAY_EN        0x100
+#define SRDSYSMOD_TXELECIDLE            0x80
+#define SRDSYSMOD_DEEMP_EN              0x40
+#define SRDSYSMOD_MS_PAD                0x4
+#define SRDSYSMOD_CDR_ADC_VLTG          0x2
+#define SRDSYSMOD_CDR_DAC_1MA           0x1
+#define SRDSYSMOD_DEF                   0x2C46
+
+#define MIIDBG_CFGLPSPD                 0x0A
+#define CFGLPSPD_RSTCNT_MASK            3U
+#define CFGLPSPD_RSTCNT_SHIFT           14
+#define CFGLPSPD_RSTCNT_CLK125SW        0x2000
+
+#define MIIDBG_HIBNEG                   0x0B
+#define HIBNEG_PSHIB_EN                 0x8000
+#define HIBNEG_WAKE_BOTH                0x4000
+#define HIBNEG_ONOFF_ANACHG_SUDEN       0x2000
+#define HIBNEG_HIB_PULSE                0x1000
+#define HIBNEG_GATE_25M_EN              0x800
+#define HIBNEG_RST_80U                  0x400
+#define HIBNEG_RST_TIMER_MASK           3U
+#define HIBNEG_RST_TIMER_SHIFT          8
+#define HIBNEG_GTX_CLK_DELAY_MASK       3U
+#define HIBNEG_GTX_CLK_DELAY_SHIFT      5
+#define HIBNEG_BYPSS_BRKTIMER           0x10
+#define HIBNEG_DEF                      0xBC40
+
+#define MIIDBG_TST10BTCFG               0x12
+#define TST10BTCFG_INTV_TIMER_MASK      3U
+#define TST10BTCFG_INTV_TIMER_SHIFT     14
+#define TST10BTCFG_TRIGER_TIMER_MASK    3U
+#define TST10BTCFG_TRIGER_TIMER_SHIFT   12
+#define TST10BTCFG_DIV_MAN_MLT3_EN      0x800
+#define TST10BTCFG_OFF_DAC_IDLE         0x400
+#define TST10BTCFG_LPBK_DEEP            0x4 /* 1:deep,0:shallow */
+#define TST10BTCFG_DEF                  0x4C04
+
+#define MIIDBG_AZ_ANADECT		0x15
+#define AZ_ANADECT_10BTRX_TH		0x8000
+#define AZ_ANADECT_BOTH_01CHNL		0x4000
+#define AZ_ANADECT_INTV_MASK		0x3FU
+#define AZ_ANADECT_INTV_SHIFT		8
+#define AZ_ANADECT_THRESH_MASK		0xFU
+#define AZ_ANADECT_THRESH_SHIFT		4
+#define AZ_ANADECT_CHNL_MASK		0xFU
+#define AZ_ANADECT_CHNL_SHIFT		0
+#define AZ_ANADECT_DEF			0x3220
+#define AZ_ANADECT_LONG                 0xb210
+
+#define MIIDBG_MSE16DB			0x18	/* l1d */
+#define L1D_MSE16DB_UP			0x05EA
+#define L1D_MSE16DB_DOWN		0x02EA
+
+#define MIIDBG_LEGCYPS                  0x29
+#define LEGCYPS_EN                      0x8000
+#define LEGCYPS_DAC_AMP1000_MASK        7U
+#define LEGCYPS_DAC_AMP1000_SHIFT       12
+#define LEGCYPS_DAC_AMP100_MASK         7U
+#define LEGCYPS_DAC_AMP100_SHIFT        9
+#define LEGCYPS_DAC_AMP10_MASK          7U
+#define LEGCYPS_DAC_AMP10_SHIFT         6
+#define LEGCYPS_UNPLUG_TIMER_MASK       7U
+#define LEGCYPS_UNPLUG_TIMER_SHIFT      3
+#define LEGCYPS_UNPLUG_DECT_EN          0x4
+#define LEGCYPS_ECNC_PS_EN              0x1
+#define L1D_LEGCYPS_DEF                 0x129D
+#define L1C_LEGCYPS_DEF                 0x36DD
+
+#define MIIDBG_TST100BTCFG              0x36
+#define TST100BTCFG_NORMAL_BW_EN        0x8000
+#define TST100BTCFG_BADLNK_BYPASS       0x4000
+#define TST100BTCFG_SHORTCABL_TH_MASK   0x3FU
+#define TST100BTCFG_SHORTCABL_TH_SHIFT  8
+#define TST100BTCFG_LITCH_EN            0x80
+#define TST100BTCFG_VLT_SW              0x40
+#define TST100BTCFG_LONGCABL_TH_MASK    0x3FU
+#define TST100BTCFG_LONGCABL_TH_SHIFT   0
+#define TST100BTCFG_DEF                 0xE12C
+
+#define MIIDBG_VOLT_CTRL                0x3B	/* only for l2cb 1 & 2 */
+#define VOLT_CTRL_CABLE1TH_MASK         0x1FFU
+#define VOLT_CTRL_CABLE1TH_SHIFT        7
+#define VOLT_CTRL_AMPCTRL_MASK          3U
+#define VOLT_CTRL_AMPCTRL_SHIFT         5
+#define VOLT_CTRL_SW_BYPASS             0x10
+#define VOLT_CTRL_SWLOWEST              0x8
+#define VOLT_CTRL_DACAMP10_MASK         7U
+#define VOLT_CTRL_DACAMP10_SHIFT        0
+
+#define MIIDBG_CABLE1TH_DET             0x3E
+#define CABLE1TH_DET_EN                 0x8000
+
+
+/******* dev 3 *********/
+#define MIIEXT_PCS                      3
 
-#define MII_ANA_CTRL_4			0x4
-#define ANA_IECHO_ADJ_MASK		0xF
-#define ANA_IECHO_ADJ_3_SHIFT		0
-#define ANA_IECHO_ADJ_2_SHIFT		4
-#define ANA_IECHO_ADJ_1_SHIFT		8
-#define ANA_IECHO_ADJ_0_SHIFT		12
+#define MIIEXT_CLDCTRL3                 0x8003
+#define CLDCTRL3_BP_CABLE1TH_DET_GT     0x8000
+#define CLDCTRL3_AZ_DISAMP              0x1000
+#define L2CB_CLDCTRL3                   0x4D19
+#define L1D_CLDCTRL3                    0xDD19
 
-#define MII_ANA_CTRL_5			0x5
-#define ANA_SERDES_CDR_BW_SHIFT		0
-#define ANA_SERDES_CDR_BW_MASK		0x3
-#define ANA_MS_PAD_DBG			0x0004
-#define ANA_SPEEDUP_DBG			0x0008
-#define ANA_SERDES_TH_LOS_SHIFT		4
-#define ANA_SERDES_TH_LOS_MASK		0x3
-#define ANA_SERDES_EN_DEEM		0x0040
-#define ANA_SERDES_TXELECIDLE		0x0080
-#define ANA_SERDES_BEACON		0x0100
-#define ANA_SERDES_HALFTXDR		0x0200
-#define ANA_SERDES_SEL_HSP		0x0400
-#define ANA_SERDES_EN_PLL		0x0800
-#define ANA_SERDES_EN			0x1000
-#define ANA_SERDES_EN_LCKDT		0x2000
+#define MIIEXT_CLDCTRL6			0x8006
+#define CLDCTRL6_CAB_LEN_MASK		0x1FFU
+#define CLDCTRL6_CAB_LEN_SHIFT          0
+#define CLDCTRL6_CAB_LEN_SHORT          0x50
 
-#define MII_ANA_CTRL_11			0xB
-#define ANA_PS_HIB_EN			0x8000
+/********* dev 7 **********/
+#define MIIEXT_ANEG                     7
 
-#define MII_ANA_CTRL_18			0x12
-#define ANA_TEST_MODE_10BT_01SHIFT	0
-#define ANA_TEST_MODE_10BT_01MASK	0x3
-#define ANA_LOOP_SEL_10BT		0x0004
-#define ANA_RGMII_MODE_SW		0x0008
-#define ANA_EN_LONGECABLE		0x0010
-#define ANA_TEST_MODE_10BT_2		0x0020
-#define ANA_EN_10BT_IDLE		0x0400
-#define ANA_EN_MASK_TB			0x0800
-#define ANA_TRIGGER_SEL_TIMER_SHIFT	12
-#define ANA_TRIGGER_SEL_TIMER_MASK	0x3
-#define ANA_INTERVAL_SEL_TIMER_SHIFT	14
-#define ANA_INTERVAL_SEL_TIMER_MASK	0x3
+#define MIIEXT_LOCAL_EEEADV             0x3C
+#define LOCAL_EEEADV_1000BT             0x4
+#define LOCAL_EEEADV_100BT              0x2
 
-#define MII_ANA_CTRL_41			0x29
-#define ANA_TOP_PS_EN			0x8000
+#define MIIEXT_REMOTE_EEEADV            0x3D
+#define REMOTE_EEEADV_1000BT            0x4
+#define REMOTE_EEEADV_100BT             0x2
 
-#define MII_ANA_CTRL_54			0x36
-#define ANA_LONG_CABLE_TH_100_SHIFT	0
-#define ANA_LONG_CABLE_TH_100_MASK	0x3F
-#define ANA_DESERVED			0x0040
-#define ANA_EN_LIT_CH			0x0080
-#define ANA_SHORT_CABLE_TH_100_SHIFT	8
-#define ANA_SHORT_CABLE_TH_100_MASK	0x3F
-#define ANA_BP_BAD_LINK_ACCUM		0x4000
-#define ANA_BP_SMALL_BW			0x8000
+#define MIIEXT_EEE_ANEG                 0x8000
+#define EEE_ANEG_1000M                  0x4
+#define EEE_ANEG_100M                   0x2
 
 #endif /*_ATL1C_HW_H_*/
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 8a1d2f9..995da22 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2314,6 +2314,7 @@ static int atl1c_suspend(struct device *dev)
 	u32 wol_ctrl_data = 0;
 	u16 mii_intr_status_data = 0;
 	u32 wufc = adapter->wol;
+	u32 phy_ctrl_data;
 
 	atl1c_disable_l0s_l1(hw);
 	if (netif_running(netdev)) {
@@ -2328,6 +2329,7 @@ static int atl1c_suspend(struct device *dev)
 
 	AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
 	AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
+	AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);
 
 	master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
 	mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT);
@@ -2336,9 +2338,13 @@ static int atl1c_suspend(struct device *dev)
 			MAC_CTRL_PRMLEN_SHIFT);
 	mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT);
 	mac_ctrl_data &= ~MAC_CTRL_DUPLX;
+	phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
+	phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
+			GPHY_CTRL_HIB_EN;
 
 	if (wufc) {
 		mac_ctrl_data |= MAC_CTRL_RX_EN;
+		phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
 		if (adapter->link_speed == SPEED_1000 ||
 			adapter->link_speed == SPEED_0) {
 			mac_ctrl_data |= atl1c_mac_speed_1000 <<
@@ -2381,23 +2387,20 @@ static int atl1c_suspend(struct device *dev)
 		dev_dbg(&pdev->dev,
 			"%s: suspend MAC=0x%x\n",
 			atl1c_driver_name, mac_ctrl_data);
-		AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
-		AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
-		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-
-		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
-			GPHY_CTRL_EXT_RESET);
 	} else {
-		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING);
 		master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS;
 		mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
 		mac_ctrl_data |= MAC_CTRL_DUPLX;
-		AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
-		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-		AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+		phy_ctrl_data |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW;
+		wol_ctrl_data = 0;
 		hw->phy_configured = false; /* re-init PHY when resume */
 	}
 
+	AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
+	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
+	AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
+
 	return 0;
 }
 
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/9] atl1c: remove PHY reset/init for link down event
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
                   ` (5 preceding siblings ...)
  2012-04-20  6:16 ` [PATCH 6/9] atl1c: update PHY reset related routine xiong
@ 2012-04-20  6:16 ` xiong
  2012-04-20  6:16 ` [PATCH 8/9] atl1c: add function atl1c_power_saving xiong
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

it's unnecessary to reset/init phy when link down.
Only L1/L2 chip (supported by atlx) need such action.

Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 995da22..cb3b3c4 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -270,8 +270,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
 		atl1c_set_aspm(hw, SPEED_0);
 		netif_carrier_off(netdev);
 		netif_stop_queue(netdev);
-		atl1c_phy_reset(hw);
-		atl1c_phy_init(&adapter->hw);
 	} else {
 		/* Link Up */
 		hw->hibernate = false;
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 8/9] atl1c: add function atl1c_power_saving
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
                   ` (6 preceding siblings ...)
  2012-04-20  6:16 ` [PATCH 7/9] atl1c: remove PHY reset/init for link down event xiong
@ 2012-04-20  6:16 ` xiong
  2012-04-20  6:16 ` [PATCH 9/9] atl1c: refine start/enable code for MAC module xiong
  2012-04-20 10:34 ` [PATCH 0/9] atl1c: update hardware settings - v3 Huang, Xiong
  9 siblings, 0 replies; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

This function is used for suspend of S1/S3/S4 and driver remove.
It sets MAC/PHY based on the WoL configuration to get lower
power consumption.
atl1c_phy_power_saving is renamed to atl1c_phy_to_ps_link, this
function is just make PHY enter a link/speed mode to eat less
power.
REG_MAC_CTRL register is 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   |   74 ++++++++++++++++---
 drivers/net/ethernet/atheros/atl1c/atl1c_hw.h   |   71 +++++++++++-------
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |   90 +----------------------
 3 files changed, 108 insertions(+), 127 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 7172d61..a077ab8 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -522,17 +522,9 @@ static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
 
 void atl1c_phy_disable(struct atl1c_hw *hw)
 {
-	u32 phy_ctrl_data;
-
-	AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);
-	phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
-	phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
-			GPHY_CTRL_HIB_EN | GPHY_CTRL_PHY_IDDQ |
-			GPHY_CTRL_PWDOWN_HW;
-	AT_WRITE_REGW(hw, REG_GPHY_CTRL, phy_ctrl_data);
+	atl1c_power_saving(hw, 0);
 }
 
-
 int atl1c_phy_reset(struct atl1c_hw *hw)
 {
 	struct atl1c_adapter *adapter = hw->adapter;
@@ -719,7 +711,8 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
 	return 0;
 }
 
-int atl1c_phy_power_saving(struct atl1c_hw *hw)
+/* select link mode to get lower power consumption */
+int atl1c_phy_to_ps_link(struct atl1c_hw *hw)
 {
 	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
 	struct pci_dev *pdev = adapter->pdev;
@@ -790,3 +783,64 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw)
 
 	return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
 }
+
+int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc)
+{
+	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	u32 master_ctrl, mac_ctrl, phy_ctrl;
+	u32 wol_ctrl, speed;
+	u16 phy_data;
+
+	wol_ctrl = 0;
+	speed = adapter->link_speed == SPEED_1000 ?
+		MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100;
+
+	AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl);
+	AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl);
+	AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl);
+
+	master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS;
+	mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed);
+	mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN);
+	if (adapter->link_duplex == FULL_DUPLEX)
+		mac_ctrl |= MAC_CTRL_DUPLX;
+	phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
+	phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
+		    GPHY_CTRL_HIB_EN;
+	if (!wufc) { /* without WoL */
+		master_ctrl |= MASTER_CTRL_CLK_SEL_DIS;
+		phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW;
+		AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);
+		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);
+		AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);
+		AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+		hw->phy_configured = false; /* re-init PHY when resume */
+		return 0;
+	}
+	phy_ctrl |= GPHY_CTRL_EXT_RESET;
+	if (wufc & AT_WUFC_MAG) {
+		mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN;
+		wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+		if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11)
+			wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN;
+	}
+	if (wufc & AT_WUFC_LNKC) {
+		wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
+		if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
+			dev_dbg(&pdev->dev, "%s: write phy MII_IER faild.\n",
+				atl1c_driver_name);
+		}
+	}
+	/* clear PHY interrupt */
+	atl1c_read_phy_reg(hw, MII_ISR, &phy_data);
+
+	dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n",
+		atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl);
+	AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);
+	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);
+	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);
+	AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl);
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 7251d11..d9bbbcb 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -48,7 +48,8 @@ bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
 int atl1c_phy_init(struct atl1c_hw *hw);
 int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
 int atl1c_restart_autoneg(struct atl1c_hw *hw);
-int atl1c_phy_power_saving(struct atl1c_hw *hw);
+int atl1c_phy_to_ps_link(struct atl1c_hw *hw);
+int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc);
 void atl1c_stop_phy_polling(struct atl1c_hw *hw);
 void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel);
 int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
@@ -62,6 +63,16 @@ int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
 int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
 int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data);
 
+/* hw-ids */
+#define PCI_DEVICE_ID_ATTANSIC_L2C      0x1062
+#define PCI_DEVICE_ID_ATTANSIC_L1C      0x1063
+#define PCI_DEVICE_ID_ATHEROS_L2C_B	0x2060 /* AR8152 v1.1 Fast 10/100 */
+#define PCI_DEVICE_ID_ATHEROS_L2C_B2	0x2062 /* AR8152 v2.0 Fast 10/100 */
+#define PCI_DEVICE_ID_ATHEROS_L1D	0x1073 /* AR8151 v1.0 Gigabit 1000 */
+#define PCI_DEVICE_ID_ATHEROS_L1D_2_0	0x1083 /* AR8151 v2.0 Gigabit 1000 */
+#define L2CB_V10			0xc0
+#define L2CB_V11			0xc1
+
 /* register definition */
 #define REG_DEVICE_CAP              	0x5C
 #define DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
@@ -365,35 +376,37 @@ int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data);
 
 /* MAC Control Register  */
 #define REG_MAC_CTRL         		0x1480
-#define MAC_CTRL_TX_EN			0x1
-#define MAC_CTRL_RX_EN			0x2
-#define MAC_CTRL_TX_FLOW		0x4
-#define MAC_CTRL_RX_FLOW            	0x8
-#define MAC_CTRL_LOOPBACK          	0x10
-#define MAC_CTRL_DUPLX              	0x20
-#define MAC_CTRL_ADD_CRC            	0x40
-#define MAC_CTRL_PAD                	0x80
-#define MAC_CTRL_LENCHK             	0x100
-#define MAC_CTRL_HUGE_EN            	0x200
-#define MAC_CTRL_PRMLEN_SHIFT       	10
-#define MAC_CTRL_PRMLEN_MASK        	0xf
-#define MAC_CTRL_RMV_VLAN           	0x4000
-#define MAC_CTRL_PROMIS_EN          	0x8000
-#define MAC_CTRL_TX_PAUSE           	0x10000
-#define MAC_CTRL_SCNT               	0x20000
-#define MAC_CTRL_SRST_TX            	0x40000
-#define MAC_CTRL_TX_SIMURST         	0x80000
+#define MAC_CTRL_SPEED_MODE_SW		BIT(30)	/* 0:phy,1:sw */
+#define MAC_CTRL_HASH_ALG_CRC32		BIT(29)	/* 1:legacy,0:lw_5b */
+#define MAC_CTRL_SINGLE_PAUSE_EN	BIT(28)
+#define MAC_CTRL_DBG			BIT(27)
+#define MAC_CTRL_BC_EN			BIT(26)
+#define MAC_CTRL_MC_ALL_EN		BIT(25)
+#define MAC_CTRL_RX_CHKSUM_EN		BIT(24)
+#define MAC_CTRL_TX_HUGE		BIT(23)
+#define MAC_CTRL_DBG_TX_BKPRESURE	BIT(22)
+#define MAC_CTRL_SPEED_MASK		3UL
 #define MAC_CTRL_SPEED_SHIFT        	20
-#define MAC_CTRL_SPEED_MASK         	0x3
-#define MAC_CTRL_DBG_TX_BKPRESURE   	0x400000
-#define MAC_CTRL_TX_HUGE            	0x800000
-#define MAC_CTRL_RX_CHKSUM_EN       	0x1000000
-#define MAC_CTRL_MC_ALL_EN          	0x2000000
-#define MAC_CTRL_BC_EN              	0x4000000
-#define MAC_CTRL_DBG                	0x8000000
-#define MAC_CTRL_SINGLE_PAUSE_EN	0x10000000
-#define MAC_CTRL_HASH_ALG_CRC32		0x20000000
-#define MAC_CTRL_SPEED_MODE_SW		0x40000000
+#define MAC_CTRL_SPEED_10_100		1
+#define MAC_CTRL_SPEED_1000		2
+#define MAC_CTRL_TX_SIMURST		BIT(19)
+#define MAC_CTRL_SCNT			BIT(17)
+#define MAC_CTRL_TX_PAUSE		BIT(16)
+#define MAC_CTRL_PROMIS_EN		BIT(15)
+#define MAC_CTRL_RMV_VLAN		BIT(14)
+#define MAC_CTRL_PRMLEN_MASK		0xFUL
+#define MAC_CTRL_PRMLEN_SHIFT		10
+#define MAC_CTRL_HUGE_EN		BIT(9)
+#define MAC_CTRL_LENCHK			BIT(8)
+#define MAC_CTRL_PAD			BIT(7)
+#define MAC_CTRL_ADD_CRC		BIT(6)
+#define MAC_CTRL_DUPLX			BIT(5)
+#define MAC_CTRL_LOOPBACK		BIT(4)
+#define MAC_CTRL_RX_FLOW		BIT(3)
+#define MAC_CTRL_TX_FLOW		BIT(2)
+#define MAC_CTRL_RX_EN			BIT(1)
+#define MAC_CTRL_TX_EN			BIT(0)
+
 
 /* MAC IPG/IFG Control Register  */
 #define REG_MAC_IPG_IFG             	0x1484
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index cb3b3c4..e989009 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -24,14 +24,6 @@
 #define ATL1C_DRV_VERSION "1.0.1.0-NAPI"
 char atl1c_driver_name[] = "atl1c";
 char atl1c_driver_version[] = ATL1C_DRV_VERSION;
-#define PCI_DEVICE_ID_ATTANSIC_L2C      0x1062
-#define PCI_DEVICE_ID_ATTANSIC_L1C      0x1063
-#define PCI_DEVICE_ID_ATHEROS_L2C_B	0x2060 /* AR8152 v1.1 Fast 10/100 */
-#define PCI_DEVICE_ID_ATHEROS_L2C_B2	0x2062 /* AR8152 v2.0 Fast 10/100 */
-#define PCI_DEVICE_ID_ATHEROS_L1D	0x1073 /* AR8151 v1.0 Gigabit 1000 */
-#define PCI_DEVICE_ID_ATHEROS_L1D_2_0	0x1083 /* AR8151 v2.0 Gigabit 1000 */
-#define L2CB_V10			0xc0
-#define L2CB_V11			0xc1
 
 /*
  * atl1c_pci_tbl - PCI Device ID Table
@@ -2307,12 +2299,7 @@ static int atl1c_suspend(struct device *dev)
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 	struct atl1c_hw *hw = &adapter->hw;
-	u32 mac_ctrl_data = 0;
-	u32 master_ctrl_data = 0;
-	u32 wol_ctrl_data = 0;
-	u16 mii_intr_status_data = 0;
 	u32 wufc = adapter->wol;
-	u32 phy_ctrl_data;
 
 	atl1c_disable_l0s_l1(hw);
 	if (netif_running(netdev)) {
@@ -2322,82 +2309,9 @@ static int atl1c_suspend(struct device *dev)
 	netif_device_detach(netdev);
 
 	if (wufc)
-		if (atl1c_phy_power_saving(hw) != 0)
+		if (atl1c_phy_to_ps_link(hw) != 0)
 			dev_dbg(&pdev->dev, "phy power saving failed");
-
-	AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
-	AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
-	AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);
-
-	master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
-	mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT);
-	mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
-			MAC_CTRL_PRMLEN_MASK) <<
-			MAC_CTRL_PRMLEN_SHIFT);
-	mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT);
-	mac_ctrl_data &= ~MAC_CTRL_DUPLX;
-	phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
-	phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
-			GPHY_CTRL_HIB_EN;
-
-	if (wufc) {
-		mac_ctrl_data |= MAC_CTRL_RX_EN;
-		phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
-		if (adapter->link_speed == SPEED_1000 ||
-			adapter->link_speed == SPEED_0) {
-			mac_ctrl_data |= atl1c_mac_speed_1000 <<
-					MAC_CTRL_SPEED_SHIFT;
-			mac_ctrl_data |= MAC_CTRL_DUPLX;
-		} else
-			mac_ctrl_data |= atl1c_mac_speed_10_100 <<
-					MAC_CTRL_SPEED_SHIFT;
-
-		if (adapter->link_duplex == DUPLEX_FULL)
-			mac_ctrl_data |= MAC_CTRL_DUPLX;
-
-		/* turn on magic packet wol */
-		if (wufc & AT_WUFC_MAG) {
-			wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
-			if (hw->nic_type == athr_l2c_b &&
-			    hw->revision_id == L2CB_V11) {
-				wol_ctrl_data |=
-					WOL_PATTERN_EN | WOL_PATTERN_PME_EN;
-			}
-		}
-		if (wufc & AT_WUFC_LNKC) {
-			wol_ctrl_data |=  WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
-			/* only link up can wake up */
-			if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
-				dev_dbg(&pdev->dev, "%s: read write phy "
-						  "register failed.\n",
-						  atl1c_driver_name);
-			}
-		}
-		/* clear phy interrupt */
-		atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
-		/* Config MAC Ctrl register */
-		__atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
-
-		/* magic packet maybe Broadcast&multicast&Unicast frame */
-		if (wufc & AT_WUFC_MAG)
-			mac_ctrl_data |= MAC_CTRL_BC_EN;
-
-		dev_dbg(&pdev->dev,
-			"%s: suspend MAC=0x%x\n",
-			atl1c_driver_name, mac_ctrl_data);
-	} else {
-		master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS;
-		mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
-		mac_ctrl_data |= MAC_CTRL_DUPLX;
-		phy_ctrl_data |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW;
-		wol_ctrl_data = 0;
-		hw->phy_configured = false; /* re-init PHY when resume */
-	}
-
-	AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
-	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
-	AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
+	atl1c_power_saving(hw, wufc);
 
 	return 0;
 }
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 9/9] atl1c: refine start/enable code for MAC module
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
                   ` (7 preceding siblings ...)
  2012-04-20  6:16 ` [PATCH 8/9] atl1c: add function atl1c_power_saving xiong
@ 2012-04-20  6:16 ` xiong
  2012-04-20 10:34 ` [PATCH 0/9] atl1c: update hardware settings - v3 Huang, Xiong
  9 siblings, 0 replies; 15+ messages in thread
From: xiong @ 2012-04-20  6:16 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel, xiong

merge TXQ/RXQ/MAC start/enable code to one function as they
are started/enabled at the same time, just like stop/disable them
in the function of atl1c_stop_mac.

Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
---
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |   89 +++++++----------------
 1 files changed, 28 insertions(+), 61 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index e989009..4902a18 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -53,11 +53,9 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(ATL1C_DRV_VERSION);
 
 static int atl1c_stop_mac(struct atl1c_hw *hw);
-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw);
-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw);
 static void atl1c_disable_l0s_l1(struct atl1c_hw *hw);
 static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed);
-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter);
+static void atl1c_start_mac(struct atl1c_adapter *adapter);
 static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter,
 		   int *work_done, int work_to_do);
 static int atl1c_up(struct atl1c_adapter *adapter);
@@ -276,9 +274,7 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
 			adapter->link_speed  = speed;
 			adapter->link_duplex = duplex;
 			atl1c_set_aspm(hw, speed);
-			atl1c_enable_tx_ctrl(hw);
-			atl1c_enable_rx_ctrl(hw);
-			atl1c_setup_mac_ctrl(adapter);
+			atl1c_start_mac(adapter);
 			if (netif_msg_link(adapter))
 				dev_info(&pdev->dev,
 					"%s: %s NIC Link is Up<%d Mbps %s>\n",
@@ -1132,22 +1128,36 @@ static int atl1c_stop_mac(struct atl1c_hw *hw)
 		IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY);
 }
 
-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw)
+static void atl1c_start_mac(struct atl1c_adapter *adapter)
 {
-	u32 data;
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 mac, txq, rxq;
 
-	AT_READ_REG(hw, REG_RXQ_CTRL, &data);
-	data |= RXQ_CTRL_EN;
-	AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
-}
+	hw->mac_duplex = adapter->link_duplex == FULL_DUPLEX ? true : false;
+	hw->mac_speed = adapter->link_speed == SPEED_1000 ?
+		atl1c_mac_speed_1000 : atl1c_mac_speed_10_100;
 
-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw)
-{
-	u32 data;
+	AT_READ_REG(hw, REG_TXQ_CTRL, &txq);
+	AT_READ_REG(hw, REG_RXQ_CTRL, &rxq);
+	AT_READ_REG(hw, REG_MAC_CTRL, &mac);
 
-	AT_READ_REG(hw, REG_TXQ_CTRL, &data);
-	data |= TXQ_CTRL_EN;
-	AT_WRITE_REG(hw, REG_TXQ_CTRL, data);
+	txq |= TXQ_CTRL_EN;
+	rxq |= RXQ_CTRL_EN;
+	mac |= MAC_CTRL_TX_EN | MAC_CTRL_TX_FLOW |
+	       MAC_CTRL_RX_EN | MAC_CTRL_RX_FLOW |
+	       MAC_CTRL_ADD_CRC | MAC_CTRL_PAD |
+	       MAC_CTRL_BC_EN | MAC_CTRL_SINGLE_PAUSE_EN |
+	       MAC_CTRL_HASH_ALG_CRC32;
+	if (hw->mac_duplex)
+		mac |= MAC_CTRL_DUPLX;
+	else
+		mac &= ~MAC_CTRL_DUPLX;
+	mac = FIELD_SETX(mac, MAC_CTRL_SPEED, hw->mac_speed);
+	mac = FIELD_SETX(mac, MAC_CTRL_PRMLEN, hw->preamble_len);
+
+	AT_WRITE_REG(hw, REG_TXQ_CTRL, txq);
+	AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq);
+	AT_WRITE_REG(hw, REG_MAC_CTRL, mac);
 }
 
 /*
@@ -1296,49 +1306,6 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed)
 	return;
 }
 
-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
-{
-	struct atl1c_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	u32 mac_ctrl_data;
-
-	mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
-	mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
-
-	if (adapter->link_duplex == FULL_DUPLEX) {
-		hw->mac_duplex = true;
-		mac_ctrl_data |= MAC_CTRL_DUPLX;
-	}
-
-	if (adapter->link_speed == SPEED_1000)
-		hw->mac_speed = atl1c_mac_speed_1000;
-	else
-		hw->mac_speed = atl1c_mac_speed_10_100;
-
-	mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) <<
-			MAC_CTRL_SPEED_SHIFT;
-
-	mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
-	mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) <<
-			MAC_CTRL_PRMLEN_SHIFT);
-
-	__atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
-
-	mac_ctrl_data |= MAC_CTRL_BC_EN;
-	if (netdev->flags & IFF_PROMISC)
-		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
-	if (netdev->flags & IFF_ALLMULTI)
-		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
-
-	mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN;
-	if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 ||
-	    hw->nic_type == athr_l1d_2) {
-		mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW;
-		mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32;
-	}
-	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-}
-
 /*
  * atl1c_configure - Configure Transmit&Receive Unit after Reset
  * @adapter: board private structure
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/9] atl1c: refine phy-register read/write function
  2012-04-20  6:16 ` [PATCH 2/9] atl1c: refine phy-register read/write function xiong
@ 2012-04-20  7:40   ` Florian Fainelli
  2012-04-20  8:54       ` Huang, Xiong
  0 siblings, 1 reply; 15+ messages in thread
From: Florian Fainelli @ 2012-04-20  7:40 UTC (permalink / raw)
  To: xiong; +Cc: davem, netdev, linux-kernel, qca-linux-team, nic-devel

Hi Xiong,

Le 04/20/12 08:16, xiong a écrit :
> phy register is read/write via MDIO control module ---
> that module will be affected by the hibernate status,
> to access phy regs in hib stutus, slow frequency clk must
> be selected.
> To access phy extension register, the MDIO related
> registers are refined/updated, a _core function is
> re-wroted for both regular PHY regs and extension regs.
> existing PHY r/w function is revised based on the _core.
> PHY extension registers will be used for the comming
> patches.
>
> Signed-off-by: xiong<xiong@qca.qualcomm.com>
> Tested-by: Liu David<dwliu@qca.qualcomm.com>
> ---
>   drivers/net/ethernet/atheros/atl1c/atl1c_hw.c   |  178 +++++++++++++++++++----
>   drivers/net/ethernet/atheros/atl1c/atl1c_hw.h   |   64 +++++---
>   drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    4 +-
>   3 files changed, 189 insertions(+), 57 deletions(-)
>
> diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> index bd1667c..6cbe78a 100644
> --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> @@ -277,65 +277,181 @@ void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
>   	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
>   }
>
> +
> +void atl1c_stop_phy_polling(struct atl1c_hw *hw)
> +{
> +	u32 val;
> +	int i;
> +
> +	if (hw->ctrl_flags&  ATL1C_FPGA_VERSION) {
> +		AT_WRITE_REG(hw, REG_MDIO_CTRL, 0);
> +		for (i = 0; i<  MDIO_MAX_AC_TO; i++) {
> +			AT_READ_REG(hw, REG_MDIO_CTRL,&val);
> +			if (0 == (val&  MDIO_CTRL_BUSY))
> +				break;
> +			udelay(10);
> +		}
> +	}
> +}

Please reduce the identation by doing this:

if (!(hw->ctrl_flags & ALT1C_FPAG_VERSION))
	return;

that makes it much more readable.

> +
> +void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel)
> +{
> +	u32 val;
> +	int i;
> +
> +	if (hw->ctrl_flags&  ATL1C_FPGA_VERSION) {
> +		val = MDIO_CTRL_SPRES_PRMBL |
> +			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
> +			FIELDX(MDIO_CTRL_REG, 1) |
> +			MDIO_CTRL_START |
> +			MDIO_CTRL_OP_READ;
> +		AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
> +		for (i = 0; i<  MDIO_MAX_AC_TO; i++) {
> +			AT_READ_REG(hw, REG_MDIO_CTRL,&val);
> +			if (0 == (val&  MDIO_CTRL_BUSY))
> +				break;
> +			udelay(10);
> +		}
> +		val |= MDIO_CTRL_AP_EN;
> +		val&= ~MDIO_CTRL_START;
> +		AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
> +		udelay(30);
> +	}
> +}

Seems like the for() busy-checking of the register could use their own 
function since it is used both in : atl1c_stop_phy_polling() and 
atl1c_start_phy_polling().

> +
> +
>   /*
> - * Reads the value from a PHY register
> - * hw - Struct containing variables accessed by shared code
> - * reg_addr - address of the PHY register to read
> + * atl1c_read_phy_core
> + * core funtion to read register in PHY via MDIO control regsiter.
> + * ext: extension register (see IEEE 802.3)
> + * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
> + * reg: reg to read
>    */
> -int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
> +int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
> +			u16 reg, u16 *phy_data)
>   {
>   	u32 val;
> +	u16 clk_sel;
>   	int i;
>
> -	val = ((u32)(reg_addr&  MDIO_REG_ADDR_MASK))<<  MDIO_REG_ADDR_SHIFT |
> -		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
> -		MDIO_CLK_25_4<<  MDIO_CLK_SEL_SHIFT;
> +	atl1c_stop_phy_polling(hw);
>
> +	*phy_data = 0;
> +	clk_sel = hw->hibernate ? MDIO_CTRL_CLK_25_128 : MDIO_CTRL_CLK_25_4;
> +	if (ext) {
> +		val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
> +		AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
> +		val = MDIO_CTRL_SPRES_PRMBL |
> +			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
> +			MDIO_CTRL_START |
> +			MDIO_CTRL_MODE_EXT |
> +			MDIO_CTRL_OP_READ;
> +	} else {
> +		val = MDIO_CTRL_SPRES_PRMBL |
> +			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
> +			FIELDX(MDIO_CTRL_REG, reg) |
> +			MDIO_CTRL_START |
> +			MDIO_CTRL_OP_READ;
> +	}
>   	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
>
> -	for (i = 0; i<  MDIO_WAIT_TIMES; i++) {
> -		udelay(2);
> +	for (i = 0; i<  MDIO_MAX_AC_TO; i++) {
>   		AT_READ_REG(hw, REG_MDIO_CTRL,&val);
> -		if (!(val&  (MDIO_START | MDIO_BUSY)))
> +		if (0 == (val&  MDIO_CTRL_BUSY)) {
> +			*phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA);
>   			break;
> +		}
> +		udelay(10);

same here, you could use the helper for busy-checking MDIO_CTRL_BUSY.

>   	}
> -	if (!(val&  (MDIO_START | MDIO_BUSY))) {
> -		*phy_data = (u16)val;
> -		return 0;
> -	}
> +	if (MDIO_MAX_AC_TO == i)
> +		return -1;
>
> -	return -1;
> +	atl1c_start_phy_polling(hw, clk_sel);
> +
> +	return 0;
>   }
>
>   /*
> - * Writes a value to a PHY register
> - * hw - Struct containing variables accessed by shared code
> - * reg_addr - address of the PHY register to write
> - * data - data to write to the PHY
> + * atl1c_write_phy_core
> + * core funtion to write to register in PHY via MDIO control regsiter.
> + * ext: extension register (see IEEE 802.3)
> + * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
> + * reg: reg to write
>    */
> -int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
> +int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
> +			u16 reg, u16 phy_data)
>   {
> -	int i;
>   	u32 val;
> +	u16 clk_sel;
> +	int i;
>
> -	val = ((u32)(phy_data&  MDIO_DATA_MASK))<<  MDIO_DATA_SHIFT   |
> -	       (reg_addr&  MDIO_REG_ADDR_MASK)<<  MDIO_REG_ADDR_SHIFT |
> -	       MDIO_SUP_PREAMBLE | MDIO_START |
> -	       MDIO_CLK_25_4<<  MDIO_CLK_SEL_SHIFT;
> +	atl1c_stop_phy_polling(hw);
>
> +	clk_sel = hw->hibernate ? MDIO_CTRL_CLK_25_128 : MDIO_CTRL_CLK_25_4;
> +	if (ext) {
> +		val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
> +		AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
> +		val = MDIO_CTRL_SPRES_PRMBL |
> +			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
> +			FIELDX(MDIO_CTRL_DATA, phy_data) |
> +			MDIO_CTRL_START |
> +			MDIO_CTRL_MODE_EXT;
> +	} else {
> +		val = MDIO_CTRL_SPRES_PRMBL |
> +			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
> +			FIELDX(MDIO_CTRL_DATA, phy_data) |
> +			FIELDX(MDIO_CTRL_REG, reg) |
> +			MDIO_CTRL_START;
> +	}
>   	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
>
> -	for (i = 0; i<  MDIO_WAIT_TIMES; i++) {
> -		udelay(2);
> +	for (i = 0; i<  MDIO_MAX_AC_TO; i++) {
>   		AT_READ_REG(hw, REG_MDIO_CTRL,&val);
> -		if (!(val&  (MDIO_START | MDIO_BUSY)))
> +		if (0 == (val&  MDIO_CTRL_BUSY))
>   			break;
> +		udelay(10);
>   	}
> +	if (MDIO_MAX_AC_TO == i)
> +		return -1;
>
> -	if (!(val&  (MDIO_START | MDIO_BUSY)))
> -		return 0;
> +	atl1c_start_phy_polling(hw, clk_sel);
>
> -	return -1;
> +	return 0;
> +}
> +
> +/*
> + * Reads the value from a PHY register
> + * hw - Struct containing variables accessed by shared code
> + * reg_addr - address of the PHY register to read
> + */
> +int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
> +{
> +	return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data);
> +}
> +
> +/*
> + * Writes a value to a PHY register
> + * hw - Struct containing variables accessed by shared code
> + * reg_addr - address of the PHY register to write
> + * data - data to write to the PHY
> + */
> +int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
> +{
> +	return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data);
> +}
> +
> +/* read from PHY extension register */
> +int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
> +			u16 reg_addr, u16 *phy_data)
> +{
> +	return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data);
> +}
> +
> +/* write to PHY extension register */
> +int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
> +			u16 reg_addr, u16 phy_data)
> +{
> +	return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data);
>   }
>
>   /*
> diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
> index 459e141..eb7f3bb 100644
> --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
> +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
> @@ -49,6 +49,16 @@ int atl1c_phy_init(struct atl1c_hw *hw);
>   int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
>   int atl1c_restart_autoneg(struct atl1c_hw *hw);
>   int atl1c_phy_power_saving(struct atl1c_hw *hw);
> +void atl1c_stop_phy_polling(struct atl1c_hw *hw);
> +void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel);
> +int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
> +			u16 reg, u16 *phy_data);
> +int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
> +			u16 reg, u16 phy_data);
> +int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
> +			u16 reg_addr, u16 *phy_data);
> +int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
> +			u16 reg_addr, u16 phy_data);
>   /* register definition */
>   #define REG_DEVICE_CAP              	0x5C
>   #define DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
> @@ -268,30 +278,36 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
>
>   /* MDIO Control Register */
>   #define REG_MDIO_CTRL           	0x1414
> -#define MDIO_DATA_MASK          	0xffff  /* On MDIO write, the 16-bit
> -						 * control data to write to PHY
> -						 * MII management register */
> -#define MDIO_DATA_SHIFT         	0       /* On MDIO read, the 16-bit
> -						 * status data that was read
> -						 * from the PHY MII management register */
> -#define MDIO_REG_ADDR_MASK      	0x1f    /* MDIO register address */
> -#define MDIO_REG_ADDR_SHIFT     	16
> -#define MDIO_RW                 	0x200000  /* 1: read, 0: write */
> -#define MDIO_SUP_PREAMBLE       	0x400000  /* Suppress preamble */
> -#define MDIO_START              	0x800000  /* Write 1 to initiate the MDIO
> -						   * master. And this bit is self
> -						   * cleared after one cycle */
> -#define MDIO_CLK_SEL_SHIFT      	24
> -#define MDIO_CLK_25_4           	0
> -#define MDIO_CLK_25_6           	2
> -#define MDIO_CLK_25_8           	3
> -#define MDIO_CLK_25_10          	4
> -#define MDIO_CLK_25_14          	5
> -#define MDIO_CLK_25_20          	6
> -#define MDIO_CLK_25_28          	7
> -#define MDIO_BUSY               	0x8000000
> -#define MDIO_AP_EN              	0x10000000
> -#define MDIO_WAIT_TIMES         	10
> +#define MDIO_CTRL_MODE_EXT		BIT(30)
> +#define MDIO_CTRL_POST_READ		BIT(29)
> +#define MDIO_CTRL_AP_EN			BIT(28)
> +#define MDIO_CTRL_BUSY			BIT(27)
> +#define MDIO_CTRL_CLK_SEL_MASK		0x7UL
> +#define MDIO_CTRL_CLK_SEL_SHIFT		24
> +#define MDIO_CTRL_CLK_25_4		0	/* 25MHz divide 4 */
> +#define MDIO_CTRL_CLK_25_6		2
> +#define MDIO_CTRL_CLK_25_8		3
> +#define MDIO_CTRL_CLK_25_10		4
> +#define MDIO_CTRL_CLK_25_32		5
> +#define MDIO_CTRL_CLK_25_64		6
> +#define MDIO_CTRL_CLK_25_128		7
> +#define MDIO_CTRL_START			BIT(23)
> +#define MDIO_CTRL_SPRES_PRMBL		BIT(22)
> +#define MDIO_CTRL_OP_READ		BIT(21)	/* 1:read, 0:write */
> +#define MDIO_CTRL_REG_MASK		0x1FUL
> +#define MDIO_CTRL_REG_SHIFT		16
> +#define MDIO_CTRL_DATA_MASK		0xFFFFUL
> +#define MDIO_CTRL_DATA_SHIFT		0
> +#define MDIO_MAX_AC_TO			120	/* 1.2ms timeout for slow clk */
> +
> +/* for extension reg access */
> +#define REG_MDIO_EXTN			0x1448
> +#define MDIO_EXTN_PORTAD_MASK		0x1FUL
> +#define MDIO_EXTN_PORTAD_SHIFT		21
> +#define MDIO_EXTN_DEVAD_MASK		0x1FUL
> +#define MDIO_EXTN_DEVAD_SHIFT		16
> +#define MDIO_EXTN_REG_MASK		0xFFFFUL
> +#define MDIO_EXTN_REG_SHIFT		0
>
>   /* BIST Control and Status Register0 (for the Packet Memory) */
>   #define REG_BIST0_CTRL              	0x141c
> diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> index a6c3f05..1f82880 100644
> --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
> @@ -2270,7 +2270,7 @@ static int atl1c_open(struct net_device *netdev)
>   		u32 phy_data;
>
>   		AT_READ_REG(&adapter->hw, REG_MDIO_CTRL,&phy_data);
> -		phy_data |= MDIO_AP_EN;
> +		phy_data |= MDIO_CTRL_AP_EN;
>   		AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data);
>   	}
>   	return 0;
> @@ -2558,7 +2558,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
>   	adapter->mii.mdio_read  = atl1c_mdio_read;
>   	adapter->mii.mdio_write = atl1c_mdio_write;
>   	adapter->mii.phy_id_mask = 0x1f;
> -	adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
> +	adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK;
>   	netif_napi_add(netdev,&adapter->napi, atl1c_clean, 64);
>   	setup_timer(&adapter->phy_config_timer, atl1c_phy_config,
>   			(unsigned long)adapter);

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 2/9] atl1c: refine phy-register read/write function
  2012-04-20  7:40   ` Florian Fainelli
@ 2012-04-20  8:54       ` Huang, Xiong
  0 siblings, 0 replies; 15+ messages in thread
From: Huang, Xiong @ 2012-04-20  8:54 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: davem, netdev, linux-kernel, qca-linux-team, nic-devel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 3342 bytes --]



> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> On Behalf Of Florian Fainelli
> Sent: Friday, April 20, 2012 15:41
> To: Huang, Xiong
> Cc: davem@davemloft.net; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; qca-linux-team; nic-devel
> Subject: Re: [PATCH 2/9] atl1c: refine phy-register read/write function
> 
> Hi Xiong,
> 
> Le 04/20/12 08:16, xiong a écrit :
> > phy register is read/write via MDIO control module --- that module
> > will be affected by the hibernate status, to access phy regs in hib
> > stutus, slow frequency clk must be selected.
> > To access phy extension register, the MDIO related registers are
> > refined/updated, a _core function is re-wroted for both regular PHY
> > regs and extension regs.
> > existing PHY r/w function is revised based on the _core.
> > PHY extension registers will be used for the comming patches.
> >
> > Signed-off-by: xiong<xiong@qca.qualcomm.com>
> > Tested-by: Liu David<dwliu@qca.qualcomm.com>
> > ---
> >   drivers/net/ethernet/atheros/atl1c/atl1c_hw.c   |  178
> +++++++++++++++++++----
> >   drivers/net/ethernet/atheros/atl1c/atl1c_hw.h   |   64 +++++---
> >   drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    4 +-
> >   3 files changed, 189 insertions(+), 57 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> > b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> > index bd1667c..6cbe78a 100644
> > --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> > +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> > @@ -277,65 +277,181 @@ void atl1c_hash_set(struct atl1c_hw *hw, u32
> hash_value)
> >   	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
> >   }
> >
> > +
> > +void atl1c_stop_phy_polling(struct atl1c_hw *hw) {
> > +	u32 val;
> > +	int i;
> > +
> > +	if (hw->ctrl_flags&  ATL1C_FPGA_VERSION) {
> > +		AT_WRITE_REG(hw, REG_MDIO_CTRL, 0);
> > +		for (i = 0; i<  MDIO_MAX_AC_TO; i++) {
> > +			AT_READ_REG(hw, REG_MDIO_CTRL,&val);
> > +			if (0 == (val&  MDIO_CTRL_BUSY))
> > +				break;
> > +			udelay(10);
> > +		}
> > +	}
> > +}
> 
> Please reduce the identation by doing this:
> 
> if (!(hw->ctrl_flags & ALT1C_FPAG_VERSION))
> 	return;
> 
> that makes it much more readable.


No problem


> > +
> > +void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel) {
> > +	u32 val;
> > +	int i;
> > +
> > +	if (hw->ctrl_flags&  ATL1C_FPGA_VERSION) {
> > +		val = MDIO_CTRL_SPRES_PRMBL |
> > +			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
> > +			FIELDX(MDIO_CTRL_REG, 1) |
> > +			MDIO_CTRL_START |
> > +			MDIO_CTRL_OP_READ;
> > +		AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
> > +		for (i = 0; i<  MDIO_MAX_AC_TO; i++) {
> > +			AT_READ_REG(hw, REG_MDIO_CTRL,&val);
> > +			if (0 == (val&  MDIO_CTRL_BUSY))
> > +				break;
> > +			udelay(10);
> > +		}
> > +		val |= MDIO_CTRL_AP_EN;
> > +		val&= ~MDIO_CTRL_START;
> > +		AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
> > +		udelay(30);
> > +	}
> > +}
> 
> Seems like the for() busy-checking of the register could use their own function
> since it is used both in : atl1c_stop_phy_polling() and atl1c_start_phy_polling().
> 

Good suggestion. I will update.

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 2/9] atl1c: refine phy-register read/write function
@ 2012-04-20  8:54       ` Huang, Xiong
  0 siblings, 0 replies; 15+ messages in thread
From: Huang, Xiong @ 2012-04-20  8:54 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: davem, netdev, linux-kernel, qca-linux-team, nic-devel



> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> On Behalf Of Florian Fainelli
> Sent: Friday, April 20, 2012 15:41
> To: Huang, Xiong
> Cc: davem@davemloft.net; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; qca-linux-team; nic-devel
> Subject: Re: [PATCH 2/9] atl1c: refine phy-register read/write function
> 
> Hi Xiong,
> 
> Le 04/20/12 08:16, xiong a écrit :
> > phy register is read/write via MDIO control module --- that module
> > will be affected by the hibernate status, to access phy regs in hib
> > stutus, slow frequency clk must be selected.
> > To access phy extension register, the MDIO related registers are
> > refined/updated, a _core function is re-wroted for both regular PHY
> > regs and extension regs.
> > existing PHY r/w function is revised based on the _core.
> > PHY extension registers will be used for the comming patches.
> >
> > Signed-off-by: xiong<xiong@qca.qualcomm.com>
> > Tested-by: Liu David<dwliu@qca.qualcomm.com>
> > ---
> >   drivers/net/ethernet/atheros/atl1c/atl1c_hw.c   |  178
> +++++++++++++++++++----
> >   drivers/net/ethernet/atheros/atl1c/atl1c_hw.h   |   64 +++++---
> >   drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    4 +-
> >   3 files changed, 189 insertions(+), 57 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> > b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> > index bd1667c..6cbe78a 100644
> > --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> > +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
> > @@ -277,65 +277,181 @@ void atl1c_hash_set(struct atl1c_hw *hw, u32
> hash_value)
> >   	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
> >   }
> >
> > +
> > +void atl1c_stop_phy_polling(struct atl1c_hw *hw) {
> > +	u32 val;
> > +	int i;
> > +
> > +	if (hw->ctrl_flags&  ATL1C_FPGA_VERSION) {
> > +		AT_WRITE_REG(hw, REG_MDIO_CTRL, 0);
> > +		for (i = 0; i<  MDIO_MAX_AC_TO; i++) {
> > +			AT_READ_REG(hw, REG_MDIO_CTRL,&val);
> > +			if (0 == (val&  MDIO_CTRL_BUSY))
> > +				break;
> > +			udelay(10);
> > +		}
> > +	}
> > +}
> 
> Please reduce the identation by doing this:
> 
> if (!(hw->ctrl_flags & ALT1C_FPAG_VERSION))
> 	return;
> 
> that makes it much more readable.


No problem


> > +
> > +void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel) {
> > +	u32 val;
> > +	int i;
> > +
> > +	if (hw->ctrl_flags&  ATL1C_FPGA_VERSION) {
> > +		val = MDIO_CTRL_SPRES_PRMBL |
> > +			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
> > +			FIELDX(MDIO_CTRL_REG, 1) |
> > +			MDIO_CTRL_START |
> > +			MDIO_CTRL_OP_READ;
> > +		AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
> > +		for (i = 0; i<  MDIO_MAX_AC_TO; i++) {
> > +			AT_READ_REG(hw, REG_MDIO_CTRL,&val);
> > +			if (0 == (val&  MDIO_CTRL_BUSY))
> > +				break;
> > +			udelay(10);
> > +		}
> > +		val |= MDIO_CTRL_AP_EN;
> > +		val&= ~MDIO_CTRL_START;
> > +		AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
> > +		udelay(30);
> > +	}
> > +}
> 
> Seems like the for() busy-checking of the register could use their own function
> since it is used both in : atl1c_stop_phy_polling() and atl1c_start_phy_polling().
> 

Good suggestion. I will update.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 0/9] atl1c: update hardware settings - v3
  2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
                   ` (8 preceding siblings ...)
  2012-04-20  6:16 ` [PATCH 9/9] atl1c: refine start/enable code for MAC module xiong
@ 2012-04-20 10:34 ` Huang, Xiong
  2012-04-20 17:20   ` David Miller
  9 siblings, 1 reply; 15+ messages in thread
From: Huang, Xiong @ 2012-04-20 10:34 UTC (permalink / raw)
  To: davem, netdev, linux-kernel; +Cc: qca-linux-team, nic-devel

Hi David

    Please ignore this patch set, we found some NICs sometimes may fail to get IP via DHCP, this issue doesn't 100% happen.
    So, after fixing it, we will re-send a new patch set.
    Any suggestion would be great appreciated. Thanks a lot !

-Xiong  

> -----Original Message-----
> From: Huang, Xiong
> Sent: Friday, April 20, 2012 14:16
> To: davem@davemloft.net; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org
> Cc: qca-linux-team; nic-devel; Huang, Xiong
> Subject: [PATCH 0/9] atl1c: update hardware settings - v3
> 
> This update contains a serial of patches, most of them are hardware settings
> related. register definitions are refined (or removed if
> meaningless) for each patch.
> 
> This is the third serial patches, after reviewed/applied the fourth serial will be
> out.
> 
> The patches have addressed all sparse and checkpatch warnings.
> 
> Following NICs are tested:
> AR8131/AR8132/AR8151A/AR8152A/AR8152B
> Test item includes:
> build/install/uninstall/dhcp/ping/iperf/wol/reboot/etc.
> 
> xiong (9):
>   atl1c: remove REG_PHY_STATUS
>   atl1c: refine phy-register read/write function
>   atl1c: remove PHY contrl in atl1c_reset_pcie
>   atl1c: refine SERDES-clock related code
>   atl1c: remove PHY polling from atl1c_open
>   atl1c: update PHY reset related routine
>   atl1c: remove PHY reset/init for link down event
>   atl1c: add function atl1c_power_saving
>   atl1c: refine start/enable code for MAC module
> 
>  drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c |    2 +-
>  drivers/net/ethernet/atheros/atl1c/atl1c_hw.c      |  422 ++++++++++++-----
>  drivers/net/ethernet/atheros/atl1c/atl1c_hw.h      |  499 +++++++++++++-------
>  drivers/net/ethernet/atheros/atl1c/atl1c_main.c    |  240 +++-------
>  4 files changed, 693 insertions(+), 470 deletions(-)
> 
> --
> 1.7.7


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/9] atl1c: update hardware settings - v3
  2012-04-20 10:34 ` [PATCH 0/9] atl1c: update hardware settings - v3 Huang, Xiong
@ 2012-04-20 17:20   ` David Miller
  0 siblings, 0 replies; 15+ messages in thread
From: David Miller @ 2012-04-20 17:20 UTC (permalink / raw)
  To: xiong; +Cc: netdev, linux-kernel, qca-linux-team, nic-devel

From: "Huang, Xiong" <xiong@qca.qualcomm.com>
Date: Fri, 20 Apr 2012 10:34:13 +0000

>     Please ignore this patch set, we found some NICs sometimes may
>     fail to get IP via DHCP, this issue doesn't 100% happen.  So,
>     after fixing it, we will re-send a new patch set.

Ok.

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2012-04-20 17:21 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-20  6:16 [PATCH 0/9] atl1c: update hardware settings - v3 xiong
2012-04-20  6:16 ` [PATCH 1/9] atl1c: remove REG_PHY_STATUS xiong
2012-04-20  6:16 ` [PATCH 2/9] atl1c: refine phy-register read/write function xiong
2012-04-20  7:40   ` Florian Fainelli
2012-04-20  8:54     ` Huang, Xiong
2012-04-20  8:54       ` Huang, Xiong
2012-04-20  6:16 ` [PATCH 3/9] atl1c: remove PHY contrl in atl1c_reset_pcie xiong
2012-04-20  6:16 ` [PATCH 4/9] atl1c: refine SERDES-clock related code xiong
2012-04-20  6:16 ` [PATCH 5/9] atl1c: remove PHY polling from atl1c_open xiong
2012-04-20  6:16 ` [PATCH 6/9] atl1c: update PHY reset related routine xiong
2012-04-20  6:16 ` [PATCH 7/9] atl1c: remove PHY reset/init for link down event xiong
2012-04-20  6:16 ` [PATCH 8/9] atl1c: add function atl1c_power_saving xiong
2012-04-20  6:16 ` [PATCH 9/9] atl1c: refine start/enable code for MAC module xiong
2012-04-20 10:34 ` [PATCH 0/9] atl1c: update hardware settings - v3 Huang, Xiong
2012-04-20 17:20   ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.