|
@@ -164,16 +164,25 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw)
|
|
|
* MDIC mode. No harm in trying again in this case since
|
|
|
* the PHY ID is unknown at this point anyway
|
|
|
*/
|
|
|
+ ret_val = phy->ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
|
|
|
if (ret_val)
|
|
|
goto out;
|
|
|
+ phy->ops.release_phy(hw);
|
|
|
|
|
|
retry_count++;
|
|
|
}
|
|
|
out:
|
|
|
/* Revert to MDIO fast mode, if applicable */
|
|
|
- if (retry_count)
|
|
|
+ if (retry_count) {
|
|
|
+ ret_val = phy->ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ return ret_val;
|
|
|
ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
|
|
|
+ phy->ops.release_phy(hw);
|
|
|
+ }
|
|
|
|
|
|
return ret_val;
|
|
|
}
|
|
@@ -354,94 +363,173 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * e1000e_read_phy_reg_igp - Read igp PHY register
|
|
|
+ * __e1000e_read_phy_reg_igp - Read igp PHY register
|
|
|
* @hw: pointer to the HW structure
|
|
|
* @offset: register offset to be read
|
|
|
* @data: pointer to the read data
|
|
|
+ * @locked: semaphore has already been acquired or not
|
|
|
*
|
|
|
* Acquires semaphore, if necessary, then reads the PHY register at offset
|
|
|
- * and storing the retrieved information in data. Release any acquired
|
|
|
+ * and stores the retrieved information in data. Release any acquired
|
|
|
* semaphores before exiting.
|
|
|
**/
|
|
|
-s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
+static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
|
|
|
+ bool locked)
|
|
|
{
|
|
|
- s32 ret_val;
|
|
|
+ s32 ret_val = 0;
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- return ret_val;
|
|
|
+ if (!locked) {
|
|
|
+ if (!(hw->phy.ops.acquire_phy))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
if (offset > MAX_PHY_MULTI_PAGE_REG) {
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw,
|
|
|
IGP01E1000_PHY_PAGE_SELECT,
|
|
|
(u16)offset);
|
|
|
- if (ret_val) {
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
- return ret_val;
|
|
|
- }
|
|
|
+ if (ret_val)
|
|
|
+ goto release;
|
|
|
}
|
|
|
|
|
|
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
|
|
|
- data);
|
|
|
-
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
+ data);
|
|
|
|
|
|
+release:
|
|
|
+ if (!locked)
|
|
|
+ hw->phy.ops.release_phy(hw);
|
|
|
+out:
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * e1000e_read_phy_reg_igp - Read igp PHY register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to be read
|
|
|
+ * @data: pointer to the read data
|
|
|
+ *
|
|
|
+ * Acquires semaphore then reads the PHY register at offset and stores the
|
|
|
+ * retrieved information in data.
|
|
|
+ * Release the acquired semaphore before exiting.
|
|
|
+ **/
|
|
|
+s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
+{
|
|
|
+ return __e1000e_read_phy_reg_igp(hw, offset, data, false);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * e1000e_read_phy_reg_igp_locked - Read igp PHY register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to be read
|
|
|
+ * @data: pointer to the read data
|
|
|
+ *
|
|
|
+ * Reads the PHY register at offset and stores the retrieved information
|
|
|
+ * in data. Assumes semaphore already acquired.
|
|
|
+ **/
|
|
|
+s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
+{
|
|
|
+ return __e1000e_read_phy_reg_igp(hw, offset, data, true);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* e1000e_write_phy_reg_igp - Write igp PHY register
|
|
|
* @hw: pointer to the HW structure
|
|
|
* @offset: register offset to write to
|
|
|
* @data: data to write at register offset
|
|
|
+ * @locked: semaphore has already been acquired or not
|
|
|
*
|
|
|
* Acquires semaphore, if necessary, then writes the data to PHY register
|
|
|
* at the offset. Release any acquired semaphores before exiting.
|
|
|
**/
|
|
|
-s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
+static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
|
|
|
+ bool locked)
|
|
|
{
|
|
|
- s32 ret_val;
|
|
|
+ s32 ret_val = 0;
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- return ret_val;
|
|
|
+ if (!locked) {
|
|
|
+ if (!(hw->phy.ops.acquire_phy))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
if (offset > MAX_PHY_MULTI_PAGE_REG) {
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw,
|
|
|
IGP01E1000_PHY_PAGE_SELECT,
|
|
|
(u16)offset);
|
|
|
- if (ret_val) {
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
- return ret_val;
|
|
|
- }
|
|
|
+ if (ret_val)
|
|
|
+ goto release;
|
|
|
}
|
|
|
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
|
|
|
data);
|
|
|
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
+release:
|
|
|
+ if (!locked)
|
|
|
+ hw->phy.ops.release_phy(hw);
|
|
|
|
|
|
+out:
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * e1000e_read_kmrn_reg - Read kumeran register
|
|
|
+ * e1000e_write_phy_reg_igp - Write igp PHY register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to write to
|
|
|
+ * @data: data to write at register offset
|
|
|
+ *
|
|
|
+ * Acquires semaphore then writes the data to PHY register
|
|
|
+ * at the offset. Release any acquired semaphores before exiting.
|
|
|
+ **/
|
|
|
+s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
+{
|
|
|
+ return __e1000e_write_phy_reg_igp(hw, offset, data, false);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * e1000e_write_phy_reg_igp_locked - Write igp 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.
|
|
|
+ **/
|
|
|
+s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
+{
|
|
|
+ return __e1000e_write_phy_reg_igp(hw, offset, data, true);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * __e1000_read_kmrn_reg - Read kumeran register
|
|
|
* @hw: pointer to the HW structure
|
|
|
* @offset: register offset to be read
|
|
|
* @data: pointer to the read data
|
|
|
+ * @locked: semaphore has already been acquired or not
|
|
|
*
|
|
|
* Acquires semaphore, if necessary. Then reads the PHY register at offset
|
|
|
* using the kumeran interface. The information retrieved is stored in data.
|
|
|
* Release any acquired semaphores before exiting.
|
|
|
**/
|
|
|
-s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
+static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
|
|
|
+ bool locked)
|
|
|
{
|
|
|
u32 kmrnctrlsta;
|
|
|
- s32 ret_val;
|
|
|
+ s32 ret_val = 0;
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- return ret_val;
|
|
|
+ if (!locked) {
|
|
|
+ if (!(hw->phy.ops.acquire_phy))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
|
|
|
E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
|
|
@@ -452,40 +540,110 @@ s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
kmrnctrlsta = er32(KMRNCTRLSTA);
|
|
|
*data = (u16)kmrnctrlsta;
|
|
|
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
+ if (!locked)
|
|
|
+ hw->phy.ops.release_phy(hw);
|
|
|
|
|
|
+out:
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * e1000e_write_kmrn_reg - Write kumeran register
|
|
|
+ * e1000e_read_kmrn_reg - Read kumeran register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to be read
|
|
|
+ * @data: pointer to the read data
|
|
|
+ *
|
|
|
+ * Acquires semaphore then reads the PHY register at offset using the
|
|
|
+ * kumeran interface. The information retrieved is stored in data.
|
|
|
+ * Release the acquired semaphore before exiting.
|
|
|
+ **/
|
|
|
+s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
+{
|
|
|
+ return __e1000_read_kmrn_reg(hw, offset, data, false);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * e1000_read_kmrn_reg_locked - Read kumeran register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to be read
|
|
|
+ * @data: pointer to the read data
|
|
|
+ *
|
|
|
+ * Reads the PHY register at offset using the kumeran interface. The
|
|
|
+ * information retrieved is stored in data.
|
|
|
+ * Assumes semaphore already acquired.
|
|
|
+ **/
|
|
|
+s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
+{
|
|
|
+ return __e1000_read_kmrn_reg(hw, offset, data, true);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * __e1000_write_kmrn_reg - Write kumeran register
|
|
|
* @hw: pointer to the HW structure
|
|
|
* @offset: register offset to write to
|
|
|
* @data: data to write at register offset
|
|
|
+ * @locked: semaphore has already been acquired or not
|
|
|
*
|
|
|
* Acquires semaphore, if necessary. Then write the data to PHY register
|
|
|
* at the offset using the kumeran interface. Release any acquired semaphores
|
|
|
* before exiting.
|
|
|
**/
|
|
|
-s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
+static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
|
|
|
+ bool locked)
|
|
|
{
|
|
|
u32 kmrnctrlsta;
|
|
|
- s32 ret_val;
|
|
|
+ s32 ret_val = 0;
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- return ret_val;
|
|
|
+ if (!locked) {
|
|
|
+ if (!(hw->phy.ops.acquire_phy))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
|
|
|
E1000_KMRNCTRLSTA_OFFSET) | data;
|
|
|
ew32(KMRNCTRLSTA, kmrnctrlsta);
|
|
|
|
|
|
udelay(2);
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
|
|
|
+ if (!locked)
|
|
|
+ hw->phy.ops.release_phy(hw);
|
|
|
+
|
|
|
+out:
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * e1000e_write_kmrn_reg - Write kumeran register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to write to
|
|
|
+ * @data: data to write at register offset
|
|
|
+ *
|
|
|
+ * Acquires semaphore then writes the data to the PHY register at the offset
|
|
|
+ * using the kumeran interface. Release the acquired semaphore before exiting.
|
|
|
+ **/
|
|
|
+s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
+{
|
|
|
+ return __e1000_write_kmrn_reg(hw, offset, data, false);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * e1000_write_kmrn_reg_locked - Write kumeran register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to write to
|
|
|
+ * @data: data to write at register offset
|
|
|
+ *
|
|
|
+ * Write the data to PHY register at the offset using the kumeran interface.
|
|
|
+ * Assumes semaphore already acquired.
|
|
|
+ **/
|
|
|
+s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
+{
|
|
|
+ return __e1000_write_kmrn_reg(hw, offset, data, true);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
|
|
|
* @hw: pointer to the HW structure
|
|
@@ -2105,6 +2263,10 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
u32 page = offset >> IGP_PAGE_SHIFT;
|
|
|
u32 page_shift = 0;
|
|
|
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ return ret_val;
|
|
|
+
|
|
|
/* 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,
|
|
@@ -2112,10 +2274,6 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- goto out;
|
|
|
-
|
|
|
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
|
|
|
|
|
|
if (offset > MAX_PHY_MULTI_PAGE_REG) {
|
|
@@ -2135,18 +2293,15 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
/* Page is shifted left, PHY expects (page x 32) */
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
|
|
|
(page << page_shift));
|
|
|
- if (ret_val) {
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
goto out;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
|
|
|
data);
|
|
|
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
-
|
|
|
out:
|
|
|
+ hw->phy.ops.release_phy(hw);
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
@@ -2167,6 +2322,10 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
u32 page = offset >> IGP_PAGE_SHIFT;
|
|
|
u32 page_shift = 0;
|
|
|
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ return ret_val;
|
|
|
+
|
|
|
/* 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,
|
|
@@ -2174,10 +2333,6 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- goto out;
|
|
|
-
|
|
|
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
|
|
|
|
|
|
if (offset > MAX_PHY_MULTI_PAGE_REG) {
|
|
@@ -2197,17 +2352,14 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
/* Page is shifted left, PHY expects (page x 32) */
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
|
|
|
(page << page_shift));
|
|
|
- if (ret_val) {
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
goto out;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
|
|
|
data);
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
-
|
|
|
out:
|
|
|
+ hw->phy.ops.release_phy(hw);
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
@@ -2226,17 +2378,17 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
s32 ret_val;
|
|
|
u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
|
|
|
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ return ret_val;
|
|
|
+
|
|
|
/* 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);
|
|
|
- return ret_val;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- return ret_val;
|
|
|
-
|
|
|
hw->phy.addr = 1;
|
|
|
|
|
|
if (offset > MAX_PHY_MULTI_PAGE_REG) {
|
|
@@ -2245,16 +2397,14 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
|
|
|
page);
|
|
|
|
|
|
- if (ret_val) {
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
- return ret_val;
|
|
|
- }
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
|
|
|
data);
|
|
|
+out:
|
|
|
hw->phy.ops.release_phy(hw);
|
|
|
-
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
@@ -2272,17 +2422,17 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
s32 ret_val;
|
|
|
u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
|
|
|
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ return ret_val;
|
|
|
+
|
|
|
/* 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);
|
|
|
- return ret_val;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- return ret_val;
|
|
|
-
|
|
|
hw->phy.addr = 1;
|
|
|
|
|
|
if (offset > MAX_PHY_MULTI_PAGE_REG) {
|
|
@@ -2290,17 +2440,15 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
|
|
|
page);
|
|
|
|
|
|
- if (ret_val) {
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
- return ret_val;
|
|
|
- }
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
|
|
|
data);
|
|
|
|
|
|
+out:
|
|
|
hw->phy.ops.release_phy(hw);
|
|
|
-
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
@@ -2320,6 +2468,8 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
* 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.
|
|
|
**/
|
|
|
static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
|
|
|
u16 *data, bool read)
|
|
@@ -2327,20 +2477,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
|
|
|
s32 ret_val;
|
|
|
u16 reg = BM_PHY_REG_NUM(offset);
|
|
|
u16 phy_reg = 0;
|
|
|
- u8 phy_acquired = 1;
|
|
|
-
|
|
|
|
|
|
/* Gig must be disabled for MDIO accesses to page 800 */
|
|
|
if ((hw->mac.type == e1000_pchlan) &&
|
|
|
(!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
|
|
|
hw_dbg(hw, "Attempting to access page 800 while gig enabled\n");
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val) {
|
|
|
- phy_acquired = 0;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
/* All operations in this function are phy address 1 */
|
|
|
hw->phy.addr = 1;
|
|
|
|
|
@@ -2397,8 +2539,6 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
|
|
|
|
|
|
out:
|
|
|
- if (phy_acquired == 1)
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
@@ -2439,52 +2579,63 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @slow: true for slow mode, false for normal mode
|
|
|
+ *
|
|
|
+ * Assumes semaphore already acquired.
|
|
|
+ **/
|
|
|
s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow)
|
|
|
{
|
|
|
s32 ret_val = 0;
|
|
|
u16 data = 0;
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- return ret_val;
|
|
|
-
|
|
|
/* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */
|
|
|
hw->phy.addr = 1;
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
|
|
|
(BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
|
|
|
- if (ret_val) {
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
- return ret_val;
|
|
|
- }
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
+
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1,
|
|
|
(0x2180 | (slow << 10)));
|
|
|
+ if (ret_val)
|
|
|
+ goto out;
|
|
|
|
|
|
/* dummy read when reverting to fast mode - throw away result */
|
|
|
if (!slow)
|
|
|
- e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data);
|
|
|
-
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
+ ret_val = e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data);
|
|
|
|
|
|
+out:
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * e1000_read_phy_reg_hv - Read HV PHY register
|
|
|
+ * __e1000_read_phy_reg_hv - Read HV PHY register
|
|
|
* @hw: pointer to the HW structure
|
|
|
* @offset: register offset to be read
|
|
|
* @data: pointer to the read data
|
|
|
+ * @locked: semaphore has already been acquired or not
|
|
|
*
|
|
|
* Acquires semaphore, if necessary, then reads the PHY register at offset
|
|
|
- * and storing the retrieved information in data. Release any acquired
|
|
|
+ * and stores the retrieved information in data. Release any acquired
|
|
|
* semaphore before exiting.
|
|
|
**/
|
|
|
-s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
+static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
|
|
|
+ bool locked)
|
|
|
{
|
|
|
s32 ret_val;
|
|
|
u16 page = BM_PHY_REG_PAGE(offset);
|
|
|
u16 reg = BM_PHY_REG_NUM(offset);
|
|
|
bool in_slow_mode = false;
|
|
|
|
|
|
+ if (!locked) {
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ return ret_val;
|
|
|
+ }
|
|
|
+
|
|
|
/* Workaround failure in MDIO access while cable is disconnected */
|
|
|
if ((hw->phy.type == e1000_phy_82577) &&
|
|
|
!(er32(STATUS) & E1000_STATUS_LU)) {
|
|
@@ -2508,10 +2659,6 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- goto out;
|
|
|
-
|
|
|
hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
|
|
|
|
|
|
if (page == HV_INTC_FC_PAGE_START)
|
|
@@ -2529,42 +2676,76 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw,
|
|
|
IGP01E1000_PHY_PAGE_SELECT,
|
|
|
(page << IGP_PAGE_SHIFT));
|
|
|
- if (ret_val) {
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
- goto out;
|
|
|
- }
|
|
|
hw->phy.addr = phy_addr;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
|
|
|
data);
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
-
|
|
|
out:
|
|
|
/* Revert to MDIO fast mode, if applicable */
|
|
|
if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
|
|
|
ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
|
|
|
|
|
|
+ if (!locked)
|
|
|
+ hw->phy.ops.release_phy(hw);
|
|
|
+
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * e1000_write_phy_reg_hv - Write HV PHY register
|
|
|
+ * e1000_read_phy_reg_hv - Read HV PHY register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to be read
|
|
|
+ * @data: pointer to the read data
|
|
|
+ *
|
|
|
+ * Acquires semaphore then reads the PHY register at offset and stores
|
|
|
+ * the retrieved information in data. Release the acquired semaphore
|
|
|
+ * before exiting.
|
|
|
+ **/
|
|
|
+s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
|
|
|
+{
|
|
|
+ return __e1000_read_phy_reg_hv(hw, offset, data, false);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * e1000_read_phy_reg_hv_locked - Read HV PHY register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to be read
|
|
|
+ * @data: pointer to the read data
|
|
|
+ *
|
|
|
+ * Reads the PHY register at offset and stores the retrieved information
|
|
|
+ * in data. Assumes semaphore already acquired.
|
|
|
+ **/
|
|
|
+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);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * __e1000_write_phy_reg_hv - Write HV PHY register
|
|
|
* @hw: pointer to the HW structure
|
|
|
* @offset: register offset to write to
|
|
|
* @data: data to write at register offset
|
|
|
+ * @locked: semaphore has already been acquired or not
|
|
|
*
|
|
|
* Acquires semaphore, if necessary, then writes the data to PHY register
|
|
|
* at the offset. Release any acquired semaphores before exiting.
|
|
|
**/
|
|
|
-s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
+static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
|
|
|
+ bool locked)
|
|
|
{
|
|
|
s32 ret_val;
|
|
|
u16 page = BM_PHY_REG_PAGE(offset);
|
|
|
u16 reg = BM_PHY_REG_NUM(offset);
|
|
|
bool in_slow_mode = false;
|
|
|
|
|
|
+ if (!locked) {
|
|
|
+ ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
+ if (ret_val)
|
|
|
+ return ret_val;
|
|
|
+ }
|
|
|
+
|
|
|
/* Workaround failure in MDIO access while cable is disconnected */
|
|
|
if ((hw->phy.type == e1000_phy_82577) &&
|
|
|
!(er32(STATUS) & E1000_STATUS_LU)) {
|
|
@@ -2588,10 +2769,6 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- goto out;
|
|
|
-
|
|
|
hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
|
|
|
|
|
|
if (page == HV_INTC_FC_PAGE_START)
|
|
@@ -2607,15 +2784,10 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
((MAX_PHY_REG_ADDRESS & reg) == 0) &&
|
|
|
(data & (1 << 11))) {
|
|
|
u16 data2 = 0x7EFF;
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
|
|
|
&data2, false);
|
|
|
if (ret_val)
|
|
|
goto out;
|
|
|
-
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val)
|
|
|
- goto out;
|
|
|
}
|
|
|
|
|
|
if (reg > MAX_PHY_MULTI_PAGE_REG) {
|
|
@@ -2630,26 +2802,52 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw,
|
|
|
IGP01E1000_PHY_PAGE_SELECT,
|
|
|
(page << IGP_PAGE_SHIFT));
|
|
|
- if (ret_val) {
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
- goto out;
|
|
|
- }
|
|
|
hw->phy.addr = phy_addr;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
|
|
|
data);
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
|
|
|
out:
|
|
|
/* Revert to MDIO fast mode, if applicable */
|
|
|
if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
|
|
|
ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
|
|
|
|
|
|
+ if (!locked)
|
|
|
+ hw->phy.ops.release_phy(hw);
|
|
|
+
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * e1000_write_phy_reg_hv - Write HV PHY register
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ * @offset: register offset to write to
|
|
|
+ * @data: data to write at register offset
|
|
|
+ *
|
|
|
+ * Acquires semaphore then writes the data to PHY register at the offset.
|
|
|
+ * Release the acquired semaphores before exiting.
|
|
|
+ **/
|
|
|
+s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
|
|
|
+{
|
|
|
+ return __e1000_write_phy_reg_hv(hw, offset, data, false);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * e1000_write_phy_reg_hv_locked - 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.
|
|
|
+ **/
|
|
|
+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);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
|
|
|
* @page: page to be accessed
|
|
@@ -2671,10 +2869,9 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page)
|
|
|
* @data: pointer to the data to be read or written
|
|
|
* @read: determines if operation is read or written
|
|
|
*
|
|
|
- * Acquires semaphore, if necessary, then reads the PHY register at offset
|
|
|
- * and storing the retreived information in data. Release any acquired
|
|
|
- * semaphores before exiting. Note that the procedure to read these regs
|
|
|
- * uses the address port and data port to read/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.
|
|
|
**/
|
|
|
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
|
|
|
u16 *data, bool read)
|
|
@@ -2682,20 +2879,12 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
|
|
|
s32 ret_val;
|
|
|
u32 addr_reg = 0;
|
|
|
u32 data_reg = 0;
|
|
|
- u8 phy_acquired = 1;
|
|
|
|
|
|
/* This takes care of the difference with desktop vs mobile phy */
|
|
|
addr_reg = (hw->phy.type == e1000_phy_82578) ?
|
|
|
I82578_ADDR_REG : I82577_ADDR_REG;
|
|
|
data_reg = addr_reg + 1;
|
|
|
|
|
|
- ret_val = hw->phy.ops.acquire_phy(hw);
|
|
|
- if (ret_val) {
|
|
|
- hw_dbg(hw, "Could not acquire PHY\n");
|
|
|
- phy_acquired = 0;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
/* All operations in this function are phy address 2 */
|
|
|
hw->phy.addr = 2;
|
|
|
|
|
@@ -2718,8 +2907,6 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
|
|
|
}
|
|
|
|
|
|
out:
|
|
|
- if (phy_acquired == 1)
|
|
|
- hw->phy.ops.release_phy(hw);
|
|
|
return ret_val;
|
|
|
}
|
|
|
|