|
@@ -36,7 +36,7 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
|
|
|
static s32 e1000_wait_autoneg(struct e1000_hw *hw);
|
|
|
static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
|
|
|
static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
|
|
|
- u16 *data, bool read);
|
|
|
+ u16 *data, bool read, bool page_set);
|
|
|
static u32 e1000_get_phy_addr_for_hv_page(u32 page);
|
|
|
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
|
|
|
u16 *data, bool read);
|
|
@@ -347,6 +347,24 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * e1000_set_page_igp - Set page as on IGP-like PHY(s)
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @page: page to set (shifted left when necessary)
|
|
|
+ *
|
|
|
+ * Sets PHY page required for PHY register access. Assumes semaphore is
|
|
|
+ * already acquired. Note, this function sets phy.addr to 1 so the caller
|
|
|
+ * must set it appropriately (if necessary) after this function returns.
|
|
|
+ **/
|
|
|
+s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
|
|
|
+{
|
|
|
+ e_dbg("Setting page 0x%x\n", page);
|
|
|
+
|
|
|
+ hw->phy.addr = 1;
|
|
|
+
|
|
|
+ return e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* __e1000e_read_phy_reg_igp - Read igp PHY register
|
|
|
* @hw: pointer to the HW structure
|
|
@@ -2418,7 +2436,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
/* Page 800 works differently than the rest so it has its own func */
|
|
|
if (page == BM_WUC_PAGE) {
|
|
|
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
|
|
|
- false);
|
|
|
+ false, false);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -2477,7 +2495,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
/* Page 800 works differently than the rest so it has its own func */
|
|
|
if (page == BM_WUC_PAGE) {
|
|
|
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
|
|
|
- true);
|
|
|
+ true, false);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -2535,7 +2553,7 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
/* Page 800 works differently than the rest so it has its own func */
|
|
|
if (page == BM_WUC_PAGE) {
|
|
|
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
|
|
|
- true);
|
|
|
+ true, false);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -2579,7 +2597,7 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
/* Page 800 works differently than the rest so it has its own func */
|
|
|
if (page == BM_WUC_PAGE) {
|
|
|
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
|
|
|
- false);
|
|
|
+ false, false);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -2603,104 +2621,163 @@ out:
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
|
|
|
+ * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
|
|
|
* @hw: pointer to the HW structure
|
|
|
- * @offset: register offset to be read or written
|
|
|
- * @data: pointer to the data to read or write
|
|
|
- * @read: determines if operation is read or write
|
|
|
+ * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
|
|
|
*
|
|
|
- * Acquires semaphore, if necessary, then reads the PHY register at offset
|
|
|
- * and storing the retrieved information in data. Release any acquired
|
|
|
- * semaphores before exiting. Note that procedure to read the wakeup
|
|
|
- * registers are different. It works as such:
|
|
|
- * 1) Set page 769, register 17, bit 2 = 1
|
|
|
- * 2) Set page to 800 for host (801 if we were manageability)
|
|
|
- * 3) Write the address using the address opcode (0x11)
|
|
|
- * 4) Read or write the data using the data opcode (0x12)
|
|
|
- * 5) Restore 769_17.2 to its original value
|
|
|
- *
|
|
|
- * Assumes semaphore already acquired.
|
|
|
+ * Assumes semaphore already acquired and phy_reg points to a valid memory
|
|
|
+ * address to store contents of the BM_WUC_ENABLE_REG register.
|
|
|
**/
|
|
|
-static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
|
|
|
- u16 *data, bool read)
|
|
|
+s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
|
|
|
{
|
|
|
s32 ret_val;
|
|
|
- u16 reg = BM_PHY_REG_NUM(offset);
|
|
|
- u16 phy_reg = 0;
|
|
|
+ u16 temp;
|
|
|
|
|
|
- /* Gig must be disabled for MDIO accesses to page 800 */
|
|
|
- if ((hw->mac.type == e1000_pchlan) &&
|
|
|
- (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
|
|
|
- e_dbg("Attempting to access page 800 while gig enabled.\n");
|
|
|
-
|
|
|
- /* All operations in this function are phy address 1 */
|
|
|
+ /* All page select, port ctrl and wakeup registers use phy address 1 */
|
|
|
hw->phy.addr = 1;
|
|
|
|
|
|
- /* Set page 769 */
|
|
|
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
|
|
|
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
|
|
|
+ /* Select Port Control Registers page */
|
|
|
+ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
|
|
|
+ if (ret_val) {
|
|
|
+ e_dbg("Could not set Port Control page\n");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
- ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
|
|
|
+ ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
|
|
|
if (ret_val) {
|
|
|
- e_dbg("Could not read PHY page 769\n");
|
|
|
+ e_dbg("Could not read PHY register %d.%d\n",
|
|
|
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /* First clear bit 4 to avoid a power state change */
|
|
|
- phy_reg &= ~(BM_WUC_HOST_WU_BIT);
|
|
|
- ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
|
|
|
+ /*
|
|
|
+ * Enable both PHY wakeup mode and Wakeup register page writes.
|
|
|
+ * Prevent a power state change by disabling ME and Host PHY wakeup.
|
|
|
+ */
|
|
|
+ temp = *phy_reg;
|
|
|
+ temp |= BM_WUC_ENABLE_BIT;
|
|
|
+ temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
|
|
|
+
|
|
|
+ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
|
|
|
if (ret_val) {
|
|
|
- e_dbg("Could not clear PHY page 769 bit 4\n");
|
|
|
+ e_dbg("Could not write PHY register %d.%d\n",
|
|
|
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /* Write bit 2 = 1, and clear bit 4 to 769_17 */
|
|
|
- ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG,
|
|
|
- phy_reg | BM_WUC_ENABLE_BIT);
|
|
|
+ /* Select Host Wakeup Registers page */
|
|
|
+ ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
|
|
|
+
|
|
|
+ /* caller now able to write registers on the Wakeup registers page */
|
|
|
+out:
|
|
|
+ return ret_val;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
|
|
|
+ *
|
|
|
+ * Restore BM_WUC_ENABLE_REG to its original value.
|
|
|
+ *
|
|
|
+ * Assumes semaphore already acquired and *phy_reg is the contents of the
|
|
|
+ * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
|
|
|
+ * caller.
|
|
|
+ **/
|
|
|
+s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
|
|
|
+{
|
|
|
+ s32 ret_val = 0;
|
|
|
+
|
|
|
+ /* Select Port Control Registers page */
|
|
|
+ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
|
|
|
if (ret_val) {
|
|
|
- e_dbg("Could not write PHY page 769 bit 2\n");
|
|
|
+ e_dbg("Could not set Port Control page\n");
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /* Select page 800 */
|
|
|
- ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
|
|
|
- (BM_WUC_PAGE << IGP_PAGE_SHIFT));
|
|
|
+ /* Restore 769.17 to its original value */
|
|
|
+ ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
|
|
|
+ if (ret_val)
|
|
|
+ e_dbg("Could not restore PHY register %d.%d\n",
|
|
|
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
|
|
|
+out:
|
|
|
+ return ret_val;
|
|
|
+}
|
|
|
|
|
|
- /* Write the page 800 offset value using opcode 0x11 */
|
|
|
+/**
|
|
|
+ * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to be read or written
|
|
|
+ * @data: pointer to the data to read or write
|
|
|
+ * @read: determines if operation is read or write
|
|
|
+ * @page_set: BM_WUC_PAGE already set and access enabled
|
|
|
+ *
|
|
|
+ * Read the PHY register at offset and store the retrieved information in
|
|
|
+ * data, or write data to PHY register at offset. Note the procedure to
|
|
|
+ * access the PHY wakeup registers is different than reading the other PHY
|
|
|
+ * registers. It works as such:
|
|
|
+ * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1
|
|
|
+ * 2) Set page to 800 for host (801 if we were manageability)
|
|
|
+ * 3) Write the address using the address opcode (0x11)
|
|
|
+ * 4) Read or write the data using the data opcode (0x12)
|
|
|
+ * 5) Restore 769.17.2 to its original value
|
|
|
+ *
|
|
|
+ * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
|
|
|
+ * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
|
|
|
+ *
|
|
|
+ * Assumes semaphore is already acquired. When page_set==true, assumes
|
|
|
+ * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
|
|
|
+ * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
|
|
|
+ **/
|
|
|
+static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
|
|
|
+ u16 *data, bool read, bool page_set)
|
|
|
+{
|
|
|
+ s32 ret_val;
|
|
|
+ u16 reg = BM_PHY_REG_NUM(offset);
|
|
|
+ u16 page = BM_PHY_REG_PAGE(offset);
|
|
|
+ u16 phy_reg = 0;
|
|
|
+
|
|
|
+ /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
|
|
|
+ if ((hw->mac.type == e1000_pchlan) &&
|
|
|
+ (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
|
|
|
+ e_dbg("Attempting to access page %d while gig enabled.\n",
|
|
|
+ page);
|
|
|
+
|
|
|
+ if (!page_set) {
|
|
|
+ /* Enable access to PHY wakeup registers */
|
|
|
+ ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
|
|
|
+ if (ret_val) {
|
|
|
+ e_dbg("Could not enable PHY wakeup reg access\n");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ e_dbg("Accessing PHY page %d reg 0x%x\n", page, reg);
|
|
|
+
|
|
|
+ /* Write the Wakeup register page offset value using opcode 0x11 */
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
|
|
|
if (ret_val) {
|
|
|
- e_dbg("Could not write address opcode to page 800\n");
|
|
|
+ e_dbg("Could not write address opcode to page %d\n", page);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
if (read) {
|
|
|
- /* Read the page 800 value using opcode 0x12 */
|
|
|
+ /* Read the Wakeup register page value using opcode 0x12 */
|
|
|
ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
|
|
|
data);
|
|
|
} else {
|
|
|
- /* Write the page 800 value using opcode 0x12 */
|
|
|
+ /* Write the Wakeup register page value using opcode 0x12 */
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
|
|
|
*data);
|
|
|
}
|
|
|
|
|
|
if (ret_val) {
|
|
|
- e_dbg("Could not access data value from page 800\n");
|
|
|
+ e_dbg("Could not access PHY reg %d.%d\n", page, reg);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Restore 769_17.2 to its original value
|
|
|
- * Set page 769
|
|
|
- */
|
|
|
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
|
|
|
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
|
|
|
-
|
|
|
- /* Clear 769_17.2 */
|
|
|
- ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
|
|
|
- if (ret_val) {
|
|
|
- e_dbg("Could not clear PHY page 769 bit 2\n");
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ if (!page_set)
|
|
|
+ ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
|
|
|
|
|
|
out:
|
|
|
return ret_val;
|
|
@@ -2792,11 +2869,12 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
|
|
|
* semaphore before exiting.
|
|
|
**/
|
|
|
static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
|
|
|
- bool locked)
|
|
|
+ bool locked, bool page_set)
|
|
|
{
|
|
|
s32 ret_val;
|
|
|
u16 page = BM_PHY_REG_PAGE(offset);
|
|
|
u16 reg = BM_PHY_REG_NUM(offset);
|
|
|
+ u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
|
|
|
|
|
|
if (!locked) {
|
|
|
ret_val = hw->phy.ops.acquire(hw);
|
|
@@ -2806,8 +2884,8 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
|
|
|
|
|
|
/* Page 800 works differently than the rest so it has its own func */
|
|
|
if (page == BM_WUC_PAGE) {
|
|
|
- ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
|
|
|
- data, true);
|
|
|
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
|
|
|
+ true, page_set);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -2817,26 +2895,25 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
|
|
|
-
|
|
|
- if (page == HV_INTC_FC_PAGE_START)
|
|
|
- page = 0;
|
|
|
+ if (!page_set) {
|
|
|
+ if (page == HV_INTC_FC_PAGE_START)
|
|
|
+ page = 0;
|
|
|
|
|
|
- if (reg > MAX_PHY_MULTI_PAGE_REG) {
|
|
|
- u32 phy_addr = hw->phy.addr;
|
|
|
+ if (reg > MAX_PHY_MULTI_PAGE_REG) {
|
|
|
+ /* Page is shifted left, PHY expects (page x 32) */
|
|
|
+ ret_val = e1000_set_page_igp(hw,
|
|
|
+ (page << IGP_PAGE_SHIFT));
|
|
|
|
|
|
- hw->phy.addr = 1;
|
|
|
-
|
|
|
- /* Page is shifted left, PHY expects (page x 32) */
|
|
|
- ret_val = e1000e_write_phy_reg_mdic(hw,
|
|
|
- IGP01E1000_PHY_PAGE_SELECT,
|
|
|
- (page << IGP_PAGE_SHIFT));
|
|
|
- hw->phy.addr = phy_addr;
|
|
|
+ hw->phy.addr = phy_addr;
|
|
|
|
|
|
- if (ret_val)
|
|
|
- goto out;
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
|
|
|
+ page << IGP_PAGE_SHIFT, reg);
|
|
|
+
|
|
|
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
|
|
|
data);
|
|
|
out:
|
|
@@ -2858,7 +2935,7 @@ out:
|
|
|
**/
|
|
|
s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
{
|
|
|
- return __e1000_read_phy_reg_hv(hw, offset, data, false);
|
|
|
+ return __e1000_read_phy_reg_hv(hw, offset, data, false, false);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2872,7 +2949,21 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
**/
|
|
|
s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
{
|
|
|
- return __e1000_read_phy_reg_hv(hw, offset, data, true);
|
|
|
+ return __e1000_read_phy_reg_hv(hw, offset, data, true, false);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * e1000_read_phy_reg_page_hv - Read HV PHY register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to write to
|
|
|
+ * @data: data to write at register offset
|
|
|
+ *
|
|
|
+ * Reads the PHY register at offset and stores the retrieved information
|
|
|
+ * in data. Assumes semaphore already acquired and page already set.
|
|
|
+ **/
|
|
|
+s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
+{
|
|
|
+ return __e1000_read_phy_reg_hv(hw, offset, data, true, true);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2886,11 +2977,12 @@ s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
* at the offset. Release any acquired semaphores before exiting.
|
|
|
**/
|
|
|
static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
|
|
|
- bool locked)
|
|
|
+ bool locked, bool page_set)
|
|
|
{
|
|
|
s32 ret_val;
|
|
|
u16 page = BM_PHY_REG_PAGE(offset);
|
|
|
u16 reg = BM_PHY_REG_NUM(offset);
|
|
|
+ u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
|
|
|
|
|
|
if (!locked) {
|
|
|
ret_val = hw->phy.ops.acquire(hw);
|
|
@@ -2900,8 +2992,8 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
|
|
|
|
|
|
/* Page 800 works differently than the rest so it has its own func */
|
|
|
if (page == BM_WUC_PAGE) {
|
|
|
- ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
|
|
|
- &data, false);
|
|
|
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
|
|
|
+ false, page_set);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -2911,42 +3003,41 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
|
|
|
-
|
|
|
- if (page == HV_INTC_FC_PAGE_START)
|
|
|
- page = 0;
|
|
|
-
|
|
|
- /*
|
|
|
- * Workaround MDIO accesses being disabled after entering IEEE Power
|
|
|
- * Down (whenever bit 11 of the PHY Control register is set)
|
|
|
- */
|
|
|
- if ((hw->phy.type == e1000_phy_82578) &&
|
|
|
- (hw->phy.revision >= 1) &&
|
|
|
- (hw->phy.addr == 2) &&
|
|
|
- ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
|
|
|
- (data & (1 << 11))) {
|
|
|
- u16 data2 = 0x7EFF;
|
|
|
- ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
|
|
|
- &data2, false);
|
|
|
- if (ret_val)
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ if (!page_set) {
|
|
|
+ if (page == HV_INTC_FC_PAGE_START)
|
|
|
+ page = 0;
|
|
|
|
|
|
- if (reg > MAX_PHY_MULTI_PAGE_REG) {
|
|
|
- u32 phy_addr = hw->phy.addr;
|
|
|
+ /*
|
|
|
+ * Workaround MDIO accesses being disabled after entering IEEE
|
|
|
+ * Power Down (when bit 11 of the PHY Control register is set)
|
|
|
+ */
|
|
|
+ if ((hw->phy.type == e1000_phy_82578) &&
|
|
|
+ (hw->phy.revision >= 1) &&
|
|
|
+ (hw->phy.addr == 2) &&
|
|
|
+ ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) {
|
|
|
+ u16 data2 = 0x7EFF;
|
|
|
+ ret_val = e1000_access_phy_debug_regs_hv(hw,
|
|
|
+ (1 << 6) | 0x3,
|
|
|
+ &data2, false);
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
- hw->phy.addr = 1;
|
|
|
+ if (reg > MAX_PHY_MULTI_PAGE_REG) {
|
|
|
+ /* Page is shifted left, PHY expects (page x 32) */
|
|
|
+ ret_val = e1000_set_page_igp(hw,
|
|
|
+ (page << IGP_PAGE_SHIFT));
|
|
|
|
|
|
- /* Page is shifted left, PHY expects (page x 32) */
|
|
|
- ret_val = e1000e_write_phy_reg_mdic(hw,
|
|
|
- IGP01E1000_PHY_PAGE_SELECT,
|
|
|
- (page << IGP_PAGE_SHIFT));
|
|
|
- hw->phy.addr = phy_addr;
|
|
|
+ hw->phy.addr = phy_addr;
|
|
|
|
|
|
- if (ret_val)
|
|
|
- goto out;
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ e_dbg("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
|
|
|
+ page << IGP_PAGE_SHIFT, reg);
|
|
|
+
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
|
|
|
data);
|
|
|
|
|
@@ -2968,7 +3059,7 @@ out:
|
|
|
**/
|
|
|
s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
{
|
|
|
- return __e1000_write_phy_reg_hv(hw, offset, data, false);
|
|
|
+ return __e1000_write_phy_reg_hv(hw, offset, data, false, false);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2982,7 +3073,21 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
**/
|
|
|
s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
{
|
|
|
- return __e1000_write_phy_reg_hv(hw, offset, data, true);
|
|
|
+ return __e1000_write_phy_reg_hv(hw, offset, data, true, false);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * e1000_write_phy_reg_page_hv - Write HV PHY register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to write to
|
|
|
+ * @data: data to write at register offset
|
|
|
+ *
|
|
|
+ * Writes the data to PHY register at the offset. Assumes semaphore
|
|
|
+ * already acquired and page already set.
|
|
|
+ **/
|
|
|
+s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
+{
|
|
|
+ return __e1000_write_phy_reg_hv(hw, offset, data, true, true);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -3004,11 +3109,12 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page)
|
|
|
* @hw: pointer to the HW structure
|
|
|
* @offset: register offset to be read or written
|
|
|
* @data: pointer to the data to be read or written
|
|
|
- * @read: determines if operation is read or written
|
|
|
+ * @read: determines if operation is read or write
|
|
|
*
|
|
|
* Reads the PHY register at offset and stores the retreived information
|
|
|
* in data. Assumes semaphore already acquired. Note that the procedure
|
|
|
- * to read these regs uses the address port and data port to read/write.
|
|
|
+ * to access these regs uses the address port and data port to read/write.
|
|
|
+ * These accesses done with PHY address 2 and without using pages.
|
|
|
**/
|
|
|
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
|
|
|
u16 *data, bool read)
|
|
@@ -3028,7 +3134,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
|
|
|
/* masking with 0x3F to remove the page from offset */
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
|
|
|
if (ret_val) {
|
|
|
- e_dbg("Could not write PHY the HV address register\n");
|
|
|
+ e_dbg("Could not write the Address Offset port register\n");
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -3039,7 +3145,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data);
|
|
|
|
|
|
if (ret_val) {
|
|
|
- e_dbg("Could not read data value from HV data register\n");
|
|
|
+ e_dbg("Could not access the Data port register\n");
|
|
|
goto out;
|
|
|
}
|
|
|
|