All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/6] net: pch_gbe: MIPS support
@ 2018-05-10 23:16 Paul Burton
  2018-05-10 23:16 ` [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask() Paul Burton
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: Paul Burton @ 2018-05-10 23:16 UTC (permalink / raw)
  To: netdev; +Cc: linux-mips, David S . Miller, Andrew Lunn, Paul Burton

The Intel EG20T Platform Controller Hub is used on the MIPS Boston
development board to provide various peripherals including ethernet.

This series migrates the pch_gbe driver's PHY support to use phylib,
implements support for device tree which we use to provide the PHY reset
GPIO, and allows the driver to be built for MIPS.

Applies atop v4.17-rc4.

Please note that I don't have access to the Intel systems (eg.
MinnowBoard v1) that make use of this driver, so am unable to test on
those. If anyone with such a system could test the series that would be
much appreciated.

v6 of the series is later than I'd hoped, but we had a product
release[1] that kept me busy. My apologies!

The series is significantly different to earlier versions - Andrew did
the legwork of converting to phylib and that simplified things
significantly. v5 contained further fixes to the driver which I've
removed from v6 such that this series is just enough to get the driver
running on the MIPS Boston platform, despite a few bugs in the interest
of a simpler & more focused patch series. I'll submit those fixes
separately.

Thanks,
    Paul

[1] https://www.mips.com/press/new-mips-i7200-processor-core-delivers-unmatched-performance-and-efficiency-for-advanced-lte5g-communications-and-networking-ic-designs/

Andrew Lunn (2):
  net: phy: at803x: Export at803x_debug_reg_mask()
  net: ethernet: pch_gbe: Convert to mdiobus and phylib

Paul Burton (4):
  net: pch_gbe: Support DeviceTree for MDIO/PHY description
  ptp: pch: Allow build on MIPS platforms
  net: pch_gbe: Allow build on MIPS platforms
  MIPS: Boston: Adjust DT for pch_gbe PHY support

 arch/mips/boot/dts/img/boston.dts             |  13 +-
 drivers/net/ethernet/oki-semi/pch_gbe/Kconfig |   5 +-
 .../net/ethernet/oki-semi/pch_gbe/Makefile    |   2 +-
 .../net/ethernet/oki-semi/pch_gbe/pch_gbe.h   |  35 +-
 .../ethernet/oki-semi/pch_gbe/pch_gbe_api.c   | 118 ------
 .../ethernet/oki-semi/pch_gbe/pch_gbe_api.h   |   8 +-
 .../oki-semi/pch_gbe/pch_gbe_ethtool.c        |  89 +---
 .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  | 382 +++++++++---------
 .../ethernet/oki-semi/pch_gbe/pch_gbe_param.c | 265 ------------
 .../ethernet/oki-semi/pch_gbe/pch_gbe_phy.c   | 377 -----------------
 .../ethernet/oki-semi/pch_gbe/pch_gbe_phy.h   |  37 --
 drivers/net/phy/at803x.c                      |   5 +-
 drivers/ptp/Kconfig                           |   2 +-
 include/linux/at803x_phy.h                    |  16 +
 14 files changed, 249 insertions(+), 1105 deletions(-)
 delete mode 100644 drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
 delete mode 100644 drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
 create mode 100644 include/linux/at803x_phy.h

-- 
2.17.0

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

* [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask()
  2018-05-10 23:16 [PATCH v6 0/6] net: pch_gbe: MIPS support Paul Burton
@ 2018-05-10 23:16 ` Paul Burton
  2018-05-11  0:26   ` Andrew Lunn
  2018-05-10 23:16 ` [PATCH v6 2/6] net: ethernet: pch_gbe: Convert to mdiobus and phylib Paul Burton
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Paul Burton @ 2018-05-10 23:16 UTC (permalink / raw)
  To: netdev; +Cc: linux-mips, David S . Miller, Andrew Lunn, Paul Burton

From: Andrew Lunn <andrew@lunn.ch>

On some boards, this PHY has a problem when it hibernates. Export this
function to a board can register a PHY fixup to disable hibernation.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org

---

Changes in v6:
- New patch.

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/net/phy/at803x.c   |  5 +++--
 include/linux/at803x_phy.h | 16 ++++++++++++++++
 2 files changed, 19 insertions(+), 2 deletions(-)
 create mode 100644 include/linux/at803x_phy.h

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 411cf1072bae..5aede5708abf 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -18,6 +18,7 @@
 #include <linux/etherdevice.h>
 #include <linux/of_gpio.h>
 #include <linux/gpio/consumer.h>
+#include <linux/at803x_phy.h>
 
 #define AT803X_INTR_ENABLE			0x12
 #define AT803X_INTR_ENABLE_AUTONEG_ERR		BIT(15)
@@ -93,8 +94,8 @@ static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg)
 	return phy_read(phydev, AT803X_DEBUG_DATA);
 }
 
-static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
-				 u16 clear, u16 set)
+int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
+			  u16 clear, u16 set)
 {
 	u16 val;
 	int ret;
diff --git a/include/linux/at803x_phy.h b/include/linux/at803x_phy.h
new file mode 100644
index 000000000000..2460c17d56ec
--- /dev/null
+++ b/include/linux/at803x_phy.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _AT803X_PHY_H
+#define _PHY_AT803X_PHY
+
+#define ATH8030_PHY_ID		0x004dd076
+#define ATH8031_PHY_ID		0x004dd074
+#define ATH8035_PHY_ID		0x004dd072
+#define AT803X_PHY_ID_MASK	0xffffffef
+
+#define AT8031_HIBERNATE	0x0B
+#define AT8031_PS_HIB_EN	0x8000 /* Hibernate enable */
+
+int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
+			  u16 clear, u16 set);
+
+#endif /* _AT803X_PHY_H */
-- 
2.17.0

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

* [PATCH v6 2/6] net: ethernet: pch_gbe: Convert to mdiobus and phylib
  2018-05-10 23:16 [PATCH v6 0/6] net: pch_gbe: MIPS support Paul Burton
  2018-05-10 23:16 ` [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask() Paul Burton
@ 2018-05-10 23:16 ` Paul Burton
  2018-05-10 23:16 ` [PATCH v6 3/6] net: pch_gbe: Support DeviceTree for MDIO/PHY description Paul Burton
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: Paul Burton @ 2018-05-10 23:16 UTC (permalink / raw)
  To: netdev; +Cc: linux-mips, David S . Miller, Andrew Lunn, Paul Burton

From: Andrew Lunn <andrew@lunn.ch>

Convert this driver to use the mdio bus and phylib infrastructure.  It
will then use the common AT803X PHY driver, rather than use its own
code. Have the shared code also handle the GPIO used to reset the PHY.
To implement disabling PHY hibernation, which appears to cause issues
on the minnow board, add a PHY fixup.

Over all, these changes should make it easier to use other PHYs with
the MAC chip, and reduces the lines of code.

[paul.burton@mips.com:
  - Select CONFIG_PHYLIB.
  - Drop selection of CONFIG_MII.
  - Restore the define of PCH_GBE_MAC_IFOP_RGMII.
  - Add GPIOF_ACTIVE_LOW to the minnow PHY reset GPIO flags.]

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org

---

Changes in v6:
- New patch.

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/net/ethernet/oki-semi/pch_gbe/Kconfig |   3 +-
 .../net/ethernet/oki-semi/pch_gbe/Makefile    |   2 +-
 .../net/ethernet/oki-semi/pch_gbe/pch_gbe.h   |  35 +-
 .../ethernet/oki-semi/pch_gbe/pch_gbe_api.c   | 118 ------
 .../ethernet/oki-semi/pch_gbe/pch_gbe_api.h   |   8 +-
 .../oki-semi/pch_gbe/pch_gbe_ethtool.c        |  89 +----
 .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  | 378 +++++++++---------
 .../ethernet/oki-semi/pch_gbe/pch_gbe_param.c | 265 ------------
 .../ethernet/oki-semi/pch_gbe/pch_gbe_phy.c   | 377 -----------------
 .../ethernet/oki-semi/pch_gbe/pch_gbe_phy.h   |  37 --
 10 files changed, 213 insertions(+), 1099 deletions(-)
 delete mode 100644 drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
 delete mode 100644 drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h

diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
index 5f7a35212796..045256e99586 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
@@ -5,9 +5,10 @@
 config PCH_GBE
 	tristate "OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE"
 	depends on PCI && (X86_32 || COMPILE_TEST)
-	select MII
 	select PTP_1588_CLOCK_PCH
 	select NET_PTP_CLASSIFY
+	select AT803X_PHY
+	select PHYLIB
 	---help---
 	  This is a gigabit ethernet driver for EG20T PCH.
 	  EG20T PCH is the platform controller hub that is used in Intel's
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Makefile b/drivers/net/ethernet/oki-semi/pch_gbe/Makefile
index 31288d4ad248..163ddda97bd1 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/Makefile
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_PCH_GBE) += pch_gbe.o
 
-pch_gbe-y := pch_gbe_phy.o pch_gbe_ethtool.o pch_gbe_param.o
+pch_gbe-y := pch_gbe_ethtool.o pch_gbe_param.o
 pch_gbe-y += pch_gbe_api.o pch_gbe_main.o
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
index 697e29dd4bd3..055cf9a2b418 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
@@ -22,7 +22,8 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/mii.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -332,23 +333,11 @@ struct pch_gbe_hw;
  * struct  pch_gbe_functions - HAL APi function pointer
  * @get_bus_info:	for pch_gbe_hal_get_bus_info
  * @init_hw:		for pch_gbe_hal_init_hw
- * @read_phy_reg:	for pch_gbe_hal_read_phy_reg
- * @write_phy_reg:	for pch_gbe_hal_write_phy_reg
- * @reset_phy:		for pch_gbe_hal_phy_hw_reset
- * @sw_reset_phy:	for pch_gbe_hal_phy_sw_reset
- * @power_up_phy:	for pch_gbe_hal_power_up_phy
- * @power_down_phy:	for pch_gbe_hal_power_down_phy
  * @read_mac_addr:	for pch_gbe_hal_read_mac_addr
  */
 struct pch_gbe_functions {
 	void (*get_bus_info) (struct pch_gbe_hw *);
 	s32 (*init_hw) (struct pch_gbe_hw *);
-	s32 (*read_phy_reg) (struct pch_gbe_hw *, u32, u16 *);
-	s32 (*write_phy_reg) (struct pch_gbe_hw *, u32, u16);
-	void (*reset_phy) (struct pch_gbe_hw *);
-	void (*sw_reset_phy) (struct pch_gbe_hw *);
-	void (*power_up_phy) (struct pch_gbe_hw *hw);
-	void (*power_down_phy) (struct pch_gbe_hw *hw);
 	s32 (*read_mac_addr) (struct pch_gbe_hw *);
 };
 
@@ -378,18 +367,10 @@ struct pch_gbe_mac_info {
 
 /**
  * struct pch_gbe_phy_info - PHY information
- * @addr:		PHY address
- * @id:			PHY's identifier
- * @revision:		PHY's revision
  * @reset_delay_us:	HW reset delay time[us]
- * @autoneg_advertised:	Autoneg advertised
  */
 struct pch_gbe_phy_info {
-	u32 addr;
-	u32 id;
-	u32 revision;
 	u32 reset_delay_us;
-	u16 autoneg_advertised;
 };
 
 /*!
@@ -578,6 +559,8 @@ struct pch_gbe_hw_stats {
 	u32 intr_tcpip_err_count;
 };
 
+struct pch_gbe_adapter;
+
 /**
  * struct pch_gbe_privdata - PCI Device ID driver data
  * @phy_tx_clk_delay:		Bool, configure the PHY TX delay in software
@@ -588,7 +571,7 @@ struct pch_gbe_hw_stats {
 struct pch_gbe_privdata {
 	bool phy_tx_clk_delay;
 	bool phy_disable_hibernate;
-	int (*platform_init)(struct pci_dev *pdev);
+	int (*platform_init)(struct pch_gbe_adapter *adapter);
 };
 
 /**
@@ -603,8 +586,8 @@ struct pch_gbe_privdata {
  * @hw:			Pointer of hardware structure
  * @stats:		Hardware status
  * @reset_task:		Reset task
- * @mii:		MII information structure
- * @watchdog_timer:	Watchdog timer list
+ * @mdiobus:		Pointer of MDIO bus structure
+ * @phydev:		Pointer of PHY device structure
  * @wake_up_evt:	Wake up event
  * @config_space:	Configuration space
  * @msg_enable:		Driver message level
@@ -628,8 +611,8 @@ struct pch_gbe_adapter {
 	struct pch_gbe_hw hw;
 	struct pch_gbe_hw_stats stats;
 	struct work_struct reset_task;
-	struct mii_if_info mii;
-	struct timer_list watchdog_timer;
+	struct mii_bus *mdiobus;
+	struct phy_device *phydev;
 	u32 wake_up_evt;
 	u32 *config_space;
 	unsigned long led_status;
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c
index 51250363566b..525f37df7f8b 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c
@@ -17,7 +17,6 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "pch_gbe.h"
-#include "pch_gbe_phy.h"
 #include "pch_gbe_api.h"
 
 /* bus type values */
@@ -57,41 +56,8 @@ static void pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw)
 	hw->bus.width = pch_gbe_bus_width_pcie_x1;
 }
 
-/**
- * pch_gbe_plat_init_hw - Initialize hardware
- * @hw:	Pointer to the HW structure
- * Returns:
- *	0:		Successfully
- *	Negative value:	Failed-EBUSY
- */
-static s32 pch_gbe_plat_init_hw(struct pch_gbe_hw *hw)
-{
-	s32 ret_val;
-
-	ret_val = pch_gbe_phy_get_id(hw);
-	if (ret_val) {
-		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
-
-		netdev_err(adapter->netdev, "pch_gbe_phy_get_id error\n");
-		return ret_val;
-	}
-	pch_gbe_phy_init_setting(hw);
-	/* Setup Mac interface option RGMII */
-#ifdef PCH_GBE_MAC_IFOP_RGMII
-	pch_gbe_phy_set_rgmii(hw);
-#endif
-	return ret_val;
-}
-
 static const struct pch_gbe_functions pch_gbe_ops = {
 	.get_bus_info      = pch_gbe_plat_get_bus_info,
-	.init_hw           = pch_gbe_plat_init_hw,
-	.read_phy_reg      = pch_gbe_phy_read_reg_miic,
-	.write_phy_reg     = pch_gbe_phy_write_reg_miic,
-	.reset_phy         = pch_gbe_phy_hw_reset,
-	.sw_reset_phy      = pch_gbe_phy_sw_reset,
-	.power_up_phy      = pch_gbe_phy_power_up,
-	.power_down_phy    = pch_gbe_phy_power_down,
 	.read_mac_addr     = pch_gbe_mac_read_mac_addr
 };
 
@@ -159,70 +125,6 @@ s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
 	return hw->func->init_hw(hw);
 }
 
-/**
- * pch_gbe_hal_read_phy_reg - Reads PHY register
- * @hw:	    Pointer to the HW structure
- * @offset: The register to read
- * @data:   The buffer to store the 16-bit read.
- * Returns:
- *	0:	Successfully
- *	Negative value:	Failed
- */
-s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset,
-					u16 *data)
-{
-	if (!hw->func->read_phy_reg)
-		return 0;
-	return hw->func->read_phy_reg(hw, offset, data);
-}
-
-/**
- * pch_gbe_hal_write_phy_reg - Writes PHY register
- * @hw:	    Pointer to the HW structure
- * @offset: The register to read
- * @data:   The value to write.
- * Returns:
- *	0:	Successfully
- *	Negative value:	Failed
- */
-s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset,
-					u16 data)
-{
-	if (!hw->func->write_phy_reg)
-		return 0;
-	return hw->func->write_phy_reg(hw, offset, data);
-}
-
-/**
- * pch_gbe_hal_phy_hw_reset - Hard PHY reset
- * @hw:	    Pointer to the HW structure
- */
-void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
-{
-	if (!hw->func->reset_phy) {
-		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
-
-		netdev_err(adapter->netdev, "ERROR: configuration\n");
-		return;
-	}
-	hw->func->reset_phy(hw);
-}
-
-/**
- * pch_gbe_hal_phy_sw_reset - Soft PHY reset
- * @hw:	    Pointer to the HW structure
- */
-void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
-{
-	if (!hw->func->sw_reset_phy) {
-		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
-
-		netdev_err(adapter->netdev, "ERROR: configuration\n");
-		return;
-	}
-	hw->func->sw_reset_phy(hw);
-}
-
 /**
  * pch_gbe_hal_read_mac_addr - Reads MAC address
  * @hw:	Pointer to the HW structure
@@ -240,23 +142,3 @@ s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
 	}
 	return hw->func->read_mac_addr(hw);
 }
-
-/**
- * pch_gbe_hal_power_up_phy - Power up PHY
- * @hw:	Pointer to the HW structure
- */
-void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
-{
-	if (hw->func->power_up_phy)
-		hw->func->power_up_phy(hw);
-}
-
-/**
- * pch_gbe_hal_power_down_phy - Power down PHY
- * @hw:	Pointer to the HW structure
- */
-void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
-{
-	if (hw->func->power_down_phy)
-		hw->func->power_down_phy(hw);
-}
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h
index 91ce07c8306c..a7a60a99fb8c 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h
@@ -19,17 +19,11 @@
 #ifndef _PCH_GBE_API_H_
 #define _PCH_GBE_API_H_
 
-#include "pch_gbe_phy.h"
+#define PCH_GBE_PHY_RESET_DELAY_US 10
 
 s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw);
 void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw);
 s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw);
-s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 *data);
-s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 data);
-void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw);
-void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw);
 s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw);
-void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw);
-void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw);
 
 #endif
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
index 731ce1e419e4..3218f6b35375 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
@@ -19,6 +19,8 @@
 #include "pch_gbe.h"
 #include "pch_gbe_api.h"
 
+#define PCH_GBE_PHY_REGS_LEN 32
+
 /**
  * pch_gbe_stats - Stats item information
  */
@@ -72,40 +74,6 @@ static const struct pch_gbe_stats pch_gbe_gstrings_stats[] = {
 
 #define PCH_GBE_MAC_REGS_LEN    (sizeof(struct pch_gbe_regs) / 4)
 #define PCH_GBE_REGS_LEN        (PCH_GBE_MAC_REGS_LEN + PCH_GBE_PHY_REGS_LEN)
-/**
- * pch_gbe_get_link_ksettings - Get device-specific settings
- * @netdev: Network interface device structure
- * @ecmd:   Ethtool command
- * Returns:
- *	0:			Successful.
- *	Negative value:		Failed.
- */
-static int pch_gbe_get_link_ksettings(struct net_device *netdev,
-				      struct ethtool_link_ksettings *ecmd)
-{
-	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-	u32 supported, advertising;
-
-	mii_ethtool_get_link_ksettings(&adapter->mii, ecmd);
-
-	ethtool_convert_link_mode_to_legacy_u32(&supported,
-						ecmd->link_modes.supported);
-	ethtool_convert_link_mode_to_legacy_u32(&advertising,
-						ecmd->link_modes.advertising);
-
-	supported &= ~(SUPPORTED_TP | SUPPORTED_1000baseT_Half);
-	advertising &= ~(ADVERTISED_TP | ADVERTISED_1000baseT_Half);
-
-	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
-						supported);
-	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
-						advertising);
-
-	if (!netif_carrier_ok(adapter->netdev))
-		ecmd->base.speed = SPEED_UNKNOWN;
-
-	return 0;
-}
 
 /**
  * pch_gbe_set_link_ksettings - Set device-specific settings
@@ -119,34 +87,21 @@ static int pch_gbe_set_link_ksettings(struct net_device *netdev,
 				      const struct ethtool_link_ksettings *ecmd)
 {
 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct phy_device *phydev = adapter->phydev;
 	struct pch_gbe_hw *hw = &adapter->hw;
-	struct ethtool_link_ksettings copy_ecmd;
-	u32 speed = ecmd->base.speed;
 	u32 advertising;
 	int ret;
 
-	pch_gbe_hal_write_phy_reg(hw, MII_BMCR, BMCR_RESET);
-
-	memcpy(&copy_ecmd, ecmd, sizeof(*ecmd));
-
-	/* when set_settings() is called with a ethtool_cmd previously
-	 * filled by get_settings() on a down link, speed is -1: */
-	if (speed == UINT_MAX) {
-		speed = SPEED_1000;
-		copy_ecmd.base.speed = speed;
-		copy_ecmd.base.duplex = DUPLEX_FULL;
-	}
-	ret = mii_ethtool_set_link_ksettings(&adapter->mii, &copy_ecmd);
+	ret = phy_ethtool_set_link_ksettings(netdev, ecmd);
 	if (ret) {
-		netdev_err(netdev, "Error: mii_ethtool_set_link_ksettings\n");
+		netdev_err(netdev, "Error: phy_ethtool_set_link_ksettings\n");
 		return ret;
 	}
-	hw->mac.link_speed = speed;
-	hw->mac.link_duplex = copy_ecmd.base.duplex;
+	hw->mac.link_speed = phydev->speed;
+	hw->mac.link_duplex = phydev->duplex;
 	ethtool_convert_link_mode_to_legacy_u32(
-		&advertising, copy_ecmd.link_modes.advertising);
-	hw->phy.autoneg_advertised = advertising;
-	hw->mac.autoneg = copy_ecmd.base.autoneg;
+		&advertising, ecmd->link_modes.advertising);
+	hw->mac.autoneg = ecmd->base.autoneg;
 
 	/* reset the link */
 	if (netif_running(adapter->netdev)) {
@@ -197,16 +152,14 @@ static void pch_gbe_get_regs(struct net_device *netdev,
 	struct pch_gbe_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
 	u32 *regs_buff = p;
-	u16 i, tmp;
+	u16 i;
 
 	regs->version = 0x1000000 | (__u32)pdev->revision << 16 | pdev->device;
 	for (i = 0; i < PCH_GBE_MAC_REGS_LEN; i++)
 		*regs_buff++ = ioread32(&hw->reg->INT_ST + i);
 	/* PHY register */
-	for (i = 0; i < PCH_GBE_PHY_REGS_LEN; i++) {
-		pch_gbe_hal_read_phy_reg(&adapter->hw, i, &tmp);
-		*regs_buff++ = tmp;
-	}
+	for (i = 0; i < PCH_GBE_PHY_REGS_LEN; i++)
+		*regs_buff++ = phy_read(adapter->phydev, i);
 }
 
 /**
@@ -261,20 +214,6 @@ static int pch_gbe_set_wol(struct net_device *netdev,
 	return 0;
 }
 
-/**
- * pch_gbe_nway_reset - Restart autonegotiation
- * @netdev: Network interface device structure
- * Returns:
- *	0:			Successful.
- *	Negative value:		Failed.
- */
-static int pch_gbe_nway_reset(struct net_device *netdev)
-{
-	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-
-	return mii_nway_restart(&adapter->mii);
-}
-
 /**
  * pch_gbe_get_ringparam - Report ring sizes
  * @netdev:  Network interface device structure
@@ -510,7 +449,7 @@ static const struct ethtool_ops pch_gbe_ethtool_ops = {
 	.get_regs = pch_gbe_get_regs,
 	.get_wol = pch_gbe_get_wol,
 	.set_wol = pch_gbe_set_wol,
-	.nway_reset = pch_gbe_nway_reset,
+	.nway_reset = phy_ethtool_nway_reset,
 	.get_link = ethtool_op_get_link,
 	.get_ringparam = pch_gbe_get_ringparam,
 	.set_ringparam = pch_gbe_set_ringparam,
@@ -519,7 +458,7 @@ static const struct ethtool_ops pch_gbe_ethtool_ops = {
 	.get_strings = pch_gbe_get_strings,
 	.get_ethtool_stats = pch_gbe_get_ethtool_stats,
 	.get_sset_count = pch_gbe_get_sset_count,
-	.get_link_ksettings = pch_gbe_get_link_ksettings,
+	.get_link_ksettings = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings = pch_gbe_set_link_ksettings,
 };
 
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 7cd494611a74..b20ed110cdef 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -23,6 +23,8 @@
 #include <linux/net_tstamp.h>
 #include <linux/ptp_classify.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/at803x_phy.h>
 
 #define DRV_VERSION     "1.01"
 const char pch_driver_version[] = DRV_VERSION;
@@ -33,7 +35,6 @@ const char pch_driver_version[] = DRV_VERSION;
 #define DSC_INIT16			0xC000
 #define PCH_GBE_DMA_ALIGN		0
 #define PCH_GBE_DMA_PADDING		2
-#define PCH_GBE_WATCHDOG_PERIOD		(5 * HZ)	/* watchdog time */
 #define PCH_GBE_COPYBREAK_DEFAULT	256
 #define PCH_GBE_PCI_BAR			1
 #define PCH_GBE_RESERVE_MEMORY		0x200000	/* 2MB */
@@ -115,9 +116,8 @@ const char pch_driver_version[] = DRV_VERSION;
 
 static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
 
-static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg);
-static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg,
-			       int data);
+#define PCH_GBE_MAC_IFOP_RGMII
+
 static void pch_gbe_set_multi(struct net_device *netdev);
 
 static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
@@ -650,6 +650,99 @@ static void pch_gbe_init_stats(struct pch_gbe_adapter *adapter)
 	return;
 }
 
+static void pch_gbe_set_mode(struct pch_gbe_adapter *adapter, u16 speed,
+			      u16 duplex)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pch_gbe_hw *hw = &adapter->hw;
+	unsigned long mode = 0;
+
+	/* Set the communication mode */
+	switch (speed) {
+	case SPEED_10:
+		mode = PCH_GBE_MODE_MII_ETHER;
+		netdev->tx_queue_len = 10;
+		break;
+	case SPEED_100:
+		mode = PCH_GBE_MODE_MII_ETHER;
+		netdev->tx_queue_len = 100;
+		break;
+	case SPEED_1000:
+		mode = PCH_GBE_MODE_GMII_ETHER;
+		break;
+	}
+	if (duplex == DUPLEX_FULL)
+		mode |= PCH_GBE_MODE_FULL_DUPLEX;
+	else
+		mode |= PCH_GBE_MODE_HALF_DUPLEX;
+	iowrite32(mode, &hw->reg->MODE);
+}
+
+static void pch_gbe_set_rgmii_ctrl(struct pch_gbe_adapter *adapter, u16 speed,
+				    u16 duplex)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	unsigned long rgmii = 0;
+
+	/* Set the RGMII control. */
+#ifdef PCH_GBE_MAC_IFOP_RGMII
+	switch (speed) {
+	case SPEED_10:
+		rgmii = (PCH_GBE_RGMII_RATE_2_5M |
+			 PCH_GBE_MAC_RGMII_CTRL_SETTING);
+		break;
+	case SPEED_100:
+		rgmii = (PCH_GBE_RGMII_RATE_25M |
+			 PCH_GBE_MAC_RGMII_CTRL_SETTING);
+		break;
+	case SPEED_1000:
+		rgmii = (PCH_GBE_RGMII_RATE_125M |
+			 PCH_GBE_MAC_RGMII_CTRL_SETTING);
+		break;
+	}
+	iowrite32(rgmii, &hw->reg->RGMII_CTRL);
+#else	/* GMII */
+	rgmii = 0;
+	iowrite32(rgmii, &hw->reg->RGMII_CTRL);
+#endif
+}
+
+/**
+ * pch_gbe_change_link - PHY has changed state
+ * @netdev:	Network interface device structure
+ */
+static void pch_gbe_change_link(struct net_device *netdev)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct phy_device *phydev = adapter->phydev;
+	struct pch_gbe_hw *hw = &adapter->hw;
+
+	if (phydev->link) {
+		netdev->tx_queue_len = adapter->tx_queue_len;
+		hw->mac.link_speed = phydev->speed;
+		hw->mac.link_duplex = phydev->duplex;
+
+		/* Set the RGMII control. */
+		pch_gbe_set_rgmii_ctrl(adapter, hw->mac.link_speed,
+						hw->mac.link_duplex);
+		/* Set the communication mode */
+		pch_gbe_set_mode(adapter, hw->mac.link_speed,
+				 hw->mac.link_duplex);
+		netif_wake_queue(netdev);
+	} else if (!phydev->link && (netif_carrier_ok(netdev))) {
+		hw->mac.link_speed = SPEED_10;
+		hw->mac.link_duplex = DUPLEX_HALF;
+		netif_stop_queue(netdev);
+	}
+	phy_print_status(phydev);
+}
+
+static int pch_gbe_phy_disable_hibernate(struct phy_device *phydev)
+{
+	return at803x_debug_reg_mask(phydev, AT8031_HIBERNATE,
+				     AT8031_PS_HIB_EN, 0);
+}
+
 /**
  * pch_gbe_init_phy - Initialize PHY
  * @adapter:  Board private structure to initialize
@@ -660,56 +753,39 @@ static void pch_gbe_init_stats(struct pch_gbe_adapter *adapter)
 static int pch_gbe_init_phy(struct pch_gbe_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
-	u32 addr;
-	u16 bmcr, stat;
-
-	/* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
-	for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) {
-		adapter->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
-		bmcr = pch_gbe_mdio_read(netdev, adapter->mii.phy_id, MII_BMCR);
-		stat = pch_gbe_mdio_read(netdev, adapter->mii.phy_id, MII_BMSR);
-		stat = pch_gbe_mdio_read(netdev, adapter->mii.phy_id, MII_BMSR);
-		if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
-			break;
-	}
-	adapter->hw.phy.addr = adapter->mii.phy_id;
-	netdev_dbg(netdev, "phy_addr = %d\n", adapter->mii.phy_id);
-	if (addr == PCH_GBE_PHY_REGS_LEN)
-		return -EAGAIN;
-	/* Selected the phy and isolate the rest */
-	for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) {
-		if (addr != adapter->mii.phy_id) {
-			pch_gbe_mdio_write(netdev, addr, MII_BMCR,
-					   BMCR_ISOLATE);
-		} else {
-			bmcr = pch_gbe_mdio_read(netdev, addr, MII_BMCR);
-			pch_gbe_mdio_write(netdev, addr, MII_BMCR,
-					   bmcr & ~BMCR_ISOLATE);
-		}
+	int ret;
+
+	if (adapter->pdata && adapter->pdata->phy_disable_hibernate)
+		phy_register_fixup(adapter->mdiobus->id,
+				   ATH8031_PHY_ID, AT803X_PHY_ID_MASK,
+				   pch_gbe_phy_disable_hibernate);
+
+	adapter->phydev = phy_find_first(adapter->mdiobus);
+	if (!adapter->phydev)
+		return -ENODEV;
+
+	ret = phy_connect_direct(netdev, adapter->phydev, pch_gbe_change_link,
+				 PHY_INTERFACE_MODE_RGMII_TXID);
+	if (ret) {
+		netdev_err(netdev, "Could not attach to PHY\n");
+		return ret;
 	}
 
-	/* MII setup */
-	adapter->mii.phy_id_mask = 0x1F;
-	adapter->mii.reg_num_mask = 0x1F;
-	adapter->mii.dev = adapter->netdev;
-	adapter->mii.mdio_read = pch_gbe_mdio_read;
-	adapter->mii.mdio_write = pch_gbe_mdio_write;
-	adapter->mii.supports_gmii = mii_check_gmii_support(&adapter->mii);
 	return 0;
 }
 
 /**
  * pch_gbe_mdio_read - The read function for mii
- * @netdev: Network interface device structure
+ * @bus: MDIO bus device structure
  * @addr:   Phy ID
  * @reg:    Access location
  * Returns:
  *	0:	Successfully
  *	Negative value:	Failed
  */
-static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg)
+static int pch_gbe_mdio_read(struct mii_bus *bus, int addr, int reg)
 {
-	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_adapter *adapter = bus->priv;
 	struct pch_gbe_hw *hw = &adapter->hw;
 
 	return pch_gbe_mac_ctrl_miim(hw, addr, PCH_GBE_HAL_MIIM_READ, reg,
@@ -718,18 +794,42 @@ static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg)
 
 /**
  * pch_gbe_mdio_write - The write function for mii
- * @netdev: Network interface device structure
- * @addr:   Phy ID (not used)
+ * @bus: MDIO bus device structure
+ * @addr:   Phy ID
  * @reg:    Access location
  * @data:   Write data
+ * Returns:
+ *	0:	Successfully
+ *	Negative value:	Failed
  */
-static void pch_gbe_mdio_write(struct net_device *netdev,
-			       int addr, int reg, int data)
+static int pch_gbe_mdio_write(struct mii_bus *bus, int addr, int reg, u16 data)
 {
-	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_adapter *adapter = bus->priv;
 	struct pch_gbe_hw *hw = &adapter->hw;
 
-	pch_gbe_mac_ctrl_miim(hw, addr, PCH_GBE_HAL_MIIM_WRITE, reg, data);
+	return pch_gbe_mac_ctrl_miim(hw, addr, PCH_GBE_HAL_MIIM_WRITE, reg,
+				     data);
+}
+
+static int pch_gbe_init_mdio(struct pch_gbe_adapter *adapter)
+{
+	struct device *dev = &adapter->pdev->dev;
+	struct mii_bus *bus;
+
+	bus = devm_mdiobus_alloc(dev);
+	if (!bus)
+		return -ENOMEM;
+
+	bus->read = pch_gbe_mdio_read;
+	bus->write = pch_gbe_mdio_write;
+	bus->parent = dev;
+	bus->name = "pch_gdb";
+	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(dev));
+	bus->priv = adapter;
+
+	adapter->mdiobus = bus;
+
+	return mdiobus_register(bus);
 }
 
 /**
@@ -1029,113 +1129,6 @@ pch_gbe_clean_rx_ring(struct pch_gbe_adapter *adapter,
 	iowrite32((rx_ring->size - 0x10), &hw->reg->RX_DSC_SIZE);
 }
 
-static void pch_gbe_set_rgmii_ctrl(struct pch_gbe_adapter *adapter, u16 speed,
-				    u16 duplex)
-{
-	struct pch_gbe_hw *hw = &adapter->hw;
-	unsigned long rgmii = 0;
-
-	/* Set the RGMII control. */
-#ifdef PCH_GBE_MAC_IFOP_RGMII
-	switch (speed) {
-	case SPEED_10:
-		rgmii = (PCH_GBE_RGMII_RATE_2_5M |
-			 PCH_GBE_MAC_RGMII_CTRL_SETTING);
-		break;
-	case SPEED_100:
-		rgmii = (PCH_GBE_RGMII_RATE_25M |
-			 PCH_GBE_MAC_RGMII_CTRL_SETTING);
-		break;
-	case SPEED_1000:
-		rgmii = (PCH_GBE_RGMII_RATE_125M |
-			 PCH_GBE_MAC_RGMII_CTRL_SETTING);
-		break;
-	}
-	iowrite32(rgmii, &hw->reg->RGMII_CTRL);
-#else	/* GMII */
-	rgmii = 0;
-	iowrite32(rgmii, &hw->reg->RGMII_CTRL);
-#endif
-}
-static void pch_gbe_set_mode(struct pch_gbe_adapter *adapter, u16 speed,
-			      u16 duplex)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct pch_gbe_hw *hw = &adapter->hw;
-	unsigned long mode = 0;
-
-	/* Set the communication mode */
-	switch (speed) {
-	case SPEED_10:
-		mode = PCH_GBE_MODE_MII_ETHER;
-		netdev->tx_queue_len = 10;
-		break;
-	case SPEED_100:
-		mode = PCH_GBE_MODE_MII_ETHER;
-		netdev->tx_queue_len = 100;
-		break;
-	case SPEED_1000:
-		mode = PCH_GBE_MODE_GMII_ETHER;
-		break;
-	}
-	if (duplex == DUPLEX_FULL)
-		mode |= PCH_GBE_MODE_FULL_DUPLEX;
-	else
-		mode |= PCH_GBE_MODE_HALF_DUPLEX;
-	iowrite32(mode, &hw->reg->MODE);
-}
-
-/**
- * pch_gbe_watchdog - Watchdog process
- * @data:  Board private structure
- */
-static void pch_gbe_watchdog(struct timer_list *t)
-{
-	struct pch_gbe_adapter *adapter = from_timer(adapter, t,
-						     watchdog_timer);
-	struct net_device *netdev = adapter->netdev;
-	struct pch_gbe_hw *hw = &adapter->hw;
-
-	netdev_dbg(netdev, "right now = %ld\n", jiffies);
-
-	pch_gbe_update_stats(adapter);
-	if ((mii_link_ok(&adapter->mii)) && (!netif_carrier_ok(netdev))) {
-		struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
-		netdev->tx_queue_len = adapter->tx_queue_len;
-		/* mii library handles link maintenance tasks */
-		if (mii_ethtool_gset(&adapter->mii, &cmd)) {
-			netdev_err(netdev, "ethtool get setting Error\n");
-			mod_timer(&adapter->watchdog_timer,
-				  round_jiffies(jiffies +
-						PCH_GBE_WATCHDOG_PERIOD));
-			return;
-		}
-		hw->mac.link_speed = ethtool_cmd_speed(&cmd);
-		hw->mac.link_duplex = cmd.duplex;
-		/* Set the RGMII control. */
-		pch_gbe_set_rgmii_ctrl(adapter, hw->mac.link_speed,
-						hw->mac.link_duplex);
-		/* Set the communication mode */
-		pch_gbe_set_mode(adapter, hw->mac.link_speed,
-				 hw->mac.link_duplex);
-		netdev_dbg(netdev,
-			   "Link is Up %d Mbps %s-Duplex\n",
-			   hw->mac.link_speed,
-			   cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
-		netif_carrier_on(netdev);
-		netif_wake_queue(netdev);
-	} else if ((!mii_link_ok(&adapter->mii)) &&
-		   (netif_carrier_ok(netdev))) {
-		netdev_dbg(netdev, "NIC Link is Down\n");
-		hw->mac.link_speed = SPEED_10;
-		hw->mac.link_duplex = DUPLEX_HALF;
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-	}
-	mod_timer(&adapter->watchdog_timer,
-		  round_jiffies(jiffies + PCH_GBE_WATCHDOG_PERIOD));
-}
-
 /**
  * pch_gbe_tx_queue - Carry out queuing of the transmission data
  * @adapter:  Board private structure
@@ -1964,8 +1957,6 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
 	pch_gbe_enable_dma_rx(&adapter->hw);
 	pch_gbe_enable_mac_rx(&adapter->hw);
 
-	mod_timer(&adapter->watchdog_timer, jiffies);
-
 	napi_enable(&adapter->napi);
 	pch_gbe_irq_enable(adapter);
 	netif_start_queue(adapter->netdev);
@@ -1996,8 +1987,6 @@ void pch_gbe_down(struct pch_gbe_adapter *adapter)
 	pch_gbe_irq_disable(adapter);
 	pch_gbe_free_irq(adapter);
 
-	del_timer_sync(&adapter->watchdog_timer);
-
 	netdev->tx_queue_len = adapter->tx_queue_len;
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
@@ -2064,7 +2053,6 @@ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter)
 static int pch_gbe_open(struct net_device *netdev)
 {
 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-	struct pch_gbe_hw *hw = &adapter->hw;
 	int err;
 
 	/* allocate transmit descriptors */
@@ -2075,7 +2063,7 @@ static int pch_gbe_open(struct net_device *netdev)
 	err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
 	if (err)
 		goto err_setup_rx;
-	pch_gbe_hal_power_up_phy(hw);
+	phy_start(adapter->phydev);
 	err = pch_gbe_up(adapter);
 	if (err)
 		goto err_up;
@@ -2083,8 +2071,7 @@ static int pch_gbe_open(struct net_device *netdev)
 	return 0;
 
 err_up:
-	if (!adapter->wake_up_evt)
-		pch_gbe_hal_power_down_phy(hw);
+	phy_stop(adapter->phydev);
 	pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
 err_setup_rx:
 	pch_gbe_free_tx_resources(adapter, adapter->tx_ring);
@@ -2103,11 +2090,9 @@ static int pch_gbe_open(struct net_device *netdev)
 static int pch_gbe_stop(struct net_device *netdev)
 {
 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-	struct pch_gbe_hw *hw = &adapter->hw;
 
 	pch_gbe_down(adapter);
-	if (!adapter->wake_up_evt)
-		pch_gbe_hal_power_down_phy(hw);
+	phy_stop(adapter->phydev);
 	pch_gbe_free_tx_resources(adapter, adapter->tx_ring);
 	pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
 	return 0;
@@ -2319,7 +2304,7 @@ static int pch_gbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 	if (cmd == SIOCSHWTSTAMP)
 		return hwtstamp_ioctl(netdev, ifr, cmd);
 
-	return generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+	return phy_mii_ioctl(adapter->phydev, ifr, cmd);
 }
 
 /**
@@ -2437,7 +2422,6 @@ static pci_ers_result_t pch_gbe_io_slot_reset(struct pci_dev *pdev)
 	}
 	pci_set_master(pdev);
 	pci_enable_wake(pdev, PCI_D0, 0);
-	pch_gbe_hal_power_up_phy(hw);
 	pch_gbe_reset(adapter);
 	/* Clear wake up status */
 	pch_gbe_mac_set_wol_event(hw, 0);
@@ -2482,7 +2466,7 @@ static int __pch_gbe_suspend(struct pci_dev *pdev)
 		pch_gbe_mac_set_wol_event(hw, wufc);
 		pci_disable_device(pdev);
 	} else {
-		pch_gbe_hal_power_down_phy(hw);
+		phy_stop(adapter->phydev);
 		pch_gbe_mac_set_wol_event(hw, wufc);
 		pci_disable_device(pdev);
 	}
@@ -2511,7 +2495,7 @@ static int pch_gbe_resume(struct device *device)
 		return err;
 	}
 	pci_set_master(pdev);
-	pch_gbe_hal_power_up_phy(hw);
+	phy_start(adapter->phydev);
 	pch_gbe_reset(adapter);
 	/* Clear wake on lan control and status */
 	pch_gbe_mac_set_wol_event(hw, 0);
@@ -2541,7 +2525,12 @@ static void pch_gbe_remove(struct pci_dev *pdev)
 	cancel_work_sync(&adapter->reset_task);
 	unregister_netdev(netdev);
 
-	pch_gbe_hal_phy_hw_reset(&adapter->hw);
+	phy_stop(adapter->phydev);
+	phy_detach(adapter->phydev);
+
+	phy_unregister_fixup(adapter->mdiobus->id, ATH8031_PHY_ID,
+			     AT803X_PHY_ID_MASK);
+	mdiobus_unregister(adapter->mdiobus);
 
 	free_netdev(netdev);
 }
@@ -2591,8 +2580,6 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 	adapter->hw.back = adapter;
 	adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR];
 	adapter->pdata = (struct pch_gbe_privdata *)pci_id->driver_data;
-	if (adapter->pdata && adapter->pdata->platform_init)
-		adapter->pdata->platform_init(pdev);
 
 	adapter->ptp_pdev =
 		pci_get_domain_bus_and_slot(pci_domain_nr(adapter->pdev->bus),
@@ -2600,7 +2587,6 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 					    PCI_DEVFN(12, 4));
 
 	netdev->netdev_ops = &pch_gbe_netdev_ops;
-	netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
 	netif_napi_add(netdev, &adapter->napi,
 		       pch_gbe_napi_poll, PCH_GBE_RX_WEIGHT);
 	netdev->hw_features = NETIF_F_RXCSUM |
@@ -2621,19 +2607,28 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 	if (ret)
 		goto err_free_netdev;
 
+	ret = pch_gbe_init_mdio(adapter);
+	if (ret) {
+		dev_err(&pdev->dev, "MDIO initialize error\n");
+		goto err_free_netdev;
+	}
+
 	/* Initialize PHY */
 	ret = pch_gbe_init_phy(adapter);
 	if (ret) {
 		dev_err(&pdev->dev, "PHY initialize error\n");
-		goto err_free_adapter;
+		goto err_free_mdiobus;
 	}
+
+	if (adapter->pdata && adapter->pdata->platform_init)
+		adapter->pdata->platform_init(adapter);
 	pch_gbe_hal_get_bus_info(&adapter->hw);
 
 	/* Read the MAC address. and store to the private data */
 	ret = pch_gbe_hal_read_mac_addr(&adapter->hw);
 	if (ret) {
 		dev_err(&pdev->dev, "MAC address Read Error\n");
-		goto err_free_adapter;
+		goto err_free_phy;
 	}
 
 	memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
@@ -2647,8 +2642,6 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 		dev_err(&pdev->dev, "Invalid MAC address, "
 		                    "interface disabled.\n");
 	}
-	timer_setup(&adapter->watchdog_timer, pch_gbe_watchdog, 0);
-
 	INIT_WORK(&adapter->reset_task, pch_gbe_reset_task);
 
 	pch_gbe_check_options(adapter);
@@ -2662,22 +2655,22 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 
 	ret = register_netdev(netdev);
 	if (ret)
-		goto err_free_adapter;
+		goto err_free_phy;
 	/* tell the stack to leave us alone until pch_gbe_open() is called */
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
 	dev_dbg(&pdev->dev, "PCH Network Connection\n");
 
-	/* Disable hibernation on certain platforms */
-	if (adapter->pdata && adapter->pdata->phy_disable_hibernate)
-		pch_gbe_phy_disable_hibernate(&adapter->hw);
-
 	device_set_wakeup_enable(&pdev->dev, 1);
 	return 0;
 
-err_free_adapter:
-	pch_gbe_hal_phy_hw_reset(&adapter->hw);
+err_free_phy:
+	phy_disconnect(adapter->phydev);
+err_free_mdiobus:
+	phy_unregister_fixup(adapter->mdiobus->id, ATH8031_PHY_ID,
+			     AT803X_PHY_ID_MASK);
+	mdiobus_unregister(adapter->mdiobus);
 err_free_netdev:
 	free_netdev(netdev);
 	return ret;
@@ -2686,24 +2679,25 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 /* The AR803X PHY on the MinnowBoard requires a physical pin to be toggled to
  * ensure it is awake for probe and init. Request the line and reset the PHY.
  */
-static int pch_gbe_minnow_platform_init(struct pci_dev *pdev)
+static int pch_gbe_minnow_platform_init(struct pch_gbe_adapter *adapter)
 {
-	unsigned long flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH | GPIOF_EXPORT;
+	unsigned long flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH |
+		GPIOF_EXPORT | GPIOF_ACTIVE_LOW;
+	struct phy_device *phydev = adapter->phydev;
+	struct device *dev = &adapter->pdev->dev;
 	unsigned gpio = MINNOW_PHY_RESET_GPIO;
 	int ret;
 
-	ret = devm_gpio_request_one(&pdev->dev, gpio, flags,
-				    "minnow_phy_reset");
+	ret = devm_gpio_request_one(dev, gpio, flags, "minnow_phy_reset");
 	if (ret) {
-		dev_err(&pdev->dev,
+		dev_err(dev,
 			"ERR: Can't request PHY reset GPIO line '%d'\n", gpio);
 		return ret;
 	}
 
-	gpio_set_value(gpio, 0);
-	usleep_range(1250, 1500);
-	gpio_set_value(gpio, 1);
-	usleep_range(1250, 1500);
+	phydev->mdio.reset = gpio_to_desc(gpio);
+	phydev->mdio.reset_assert_delay = 1500;
+	phydev->mdio.reset_deassert_delay = 1500;
 
 	return ret;
 }
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
index e097e6baaac4..c1fd66cadc76 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
@@ -42,60 +42,6 @@ static int RxDescriptors = OPTION_UNSET;
 module_param(RxDescriptors, int, 0);
 MODULE_PARM_DESC(RxDescriptors, "Number of receive descriptors");
 
-/**
- * Speed - User Specified Speed Override
- * @Valid Range: 0, 10, 100, 1000
- *   - 0:    auto-negotiate at all supported speeds
- *   - 10:   only link at 10 Mbps
- *   - 100:  only link at 100 Mbps
- *   - 1000: only link at 1000 Mbps
- * @Default Value: 0
- */
-static int Speed = OPTION_UNSET;
-module_param(Speed, int, 0);
-MODULE_PARM_DESC(Speed, "Speed setting");
-
-/**
- * Duplex - User Specified Duplex Override
- * @Valid Range: 0-2
- *   - 0:  auto-negotiate for duplex
- *   - 1:  only link at half duplex
- *   - 2:  only link at full duplex
- * @Default Value: 0
- */
-static int Duplex = OPTION_UNSET;
-module_param(Duplex, int, 0);
-MODULE_PARM_DESC(Duplex, "Duplex setting");
-
-#define HALF_DUPLEX 1
-#define FULL_DUPLEX 2
-
-/**
- * AutoNeg - Auto-negotiation Advertisement Override
- * @Valid Range: 0x01-0x0F, 0x20-0x2F
- *
- *       The AutoNeg value is a bit mask describing which speed and duplex
- *       combinations should be advertised during auto-negotiation.
- *       The supported speed and duplex modes are listed below
- *
- *       Bit           7     6     5      4      3     2     1      0
- *       Speed (Mbps)  N/A   N/A   1000   N/A    100   100   10     10
- *       Duplex                    Full          Full  Half  Full   Half
- *
- * @Default Value: 0x2F (copper)
- */
-static int AutoNeg = OPTION_UNSET;
-module_param(AutoNeg, int, 0);
-MODULE_PARM_DESC(AutoNeg, "Advertised auto-negotiation setting");
-
-#define PHY_ADVERTISE_10_HALF      0x0001
-#define PHY_ADVERTISE_10_FULL      0x0002
-#define PHY_ADVERTISE_100_HALF     0x0004
-#define PHY_ADVERTISE_100_FULL     0x0008
-#define PHY_ADVERTISE_1000_HALF    0x0010 /* Not used, just FYI */
-#define PHY_ADVERTISE_1000_FULL    0x0020
-#define PCH_AUTONEG_ADVERTISE_DEFAULT   0x2F
-
 /**
  * FlowControl - User Specified Flow Control Override
  * @Valid Range: 0-3
@@ -159,54 +105,6 @@ struct pch_gbe_option {
 	} arg;
 };
 
-static const struct pch_gbe_opt_list speed_list[] = {
-	{ 0, "" },
-	{ SPEED_10, "" },
-	{ SPEED_100, "" },
-	{ SPEED_1000, "" }
-};
-
-static const struct pch_gbe_opt_list dplx_list[] = {
-	{ 0, "" },
-	{ HALF_DUPLEX, "" },
-	{ FULL_DUPLEX, "" }
-};
-
-static const struct pch_gbe_opt_list an_list[] =
-	#define AA "AutoNeg advertising "
-	{{ 0x01, AA "10/HD" },
-	 { 0x02, AA "10/FD" },
-	 { 0x03, AA "10/FD, 10/HD" },
-	 { 0x04, AA "100/HD" },
-	 { 0x05, AA "100/HD, 10/HD" },
-	 { 0x06, AA "100/HD, 10/FD" },
-	 { 0x07, AA "100/HD, 10/FD, 10/HD" },
-	 { 0x08, AA "100/FD" },
-	 { 0x09, AA "100/FD, 10/HD" },
-	 { 0x0a, AA "100/FD, 10/FD" },
-	 { 0x0b, AA "100/FD, 10/FD, 10/HD" },
-	 { 0x0c, AA "100/FD, 100/HD" },
-	 { 0x0d, AA "100/FD, 100/HD, 10/HD" },
-	 { 0x0e, AA "100/FD, 100/HD, 10/FD" },
-	 { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
-	 { 0x20, AA "1000/FD" },
-	 { 0x21, AA "1000/FD, 10/HD" },
-	 { 0x22, AA "1000/FD, 10/FD" },
-	 { 0x23, AA "1000/FD, 10/FD, 10/HD" },
-	 { 0x24, AA "1000/FD, 100/HD" },
-	 { 0x25, AA "1000/FD, 100/HD, 10/HD" },
-	 { 0x26, AA "1000/FD, 100/HD, 10/FD" },
-	 { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
-	 { 0x28, AA "1000/FD, 100/FD" },
-	 { 0x29, AA "1000/FD, 100/FD, 10/HD" },
-	 { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
-	 { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
-	 { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
-	 { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
-	 { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
-	 { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }
-};
-
 static const struct pch_gbe_opt_list fc_list[] = {
 	{ PCH_GBE_FC_NONE, "Flow Control Disabled" },
 	{ PCH_GBE_FC_RX_PAUSE, "Flow Control Receive Only" },
@@ -275,167 +173,6 @@ static int pch_gbe_validate_option(int *value,
 	return -1;
 }
 
-/**
- * pch_gbe_check_copper_options - Range Checking for Link Options, Copper Version
- * @adapter:  Board private structure
- */
-static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
-{
-	struct pch_gbe_hw *hw = &adapter->hw;
-	int speed, dplx;
-
-	{ /* Speed */
-		static const struct pch_gbe_option opt = {
-			.type = list_option,
-			.name = "Speed",
-			.err  = "parameter ignored",
-			.def  = 0,
-			.arg  = { .l = { .nr = (int)ARRAY_SIZE(speed_list),
-					 .p = speed_list } }
-		};
-		speed = Speed;
-		pch_gbe_validate_option(&speed, &opt, adapter);
-	}
-	{ /* Duplex */
-		static const struct pch_gbe_option opt = {
-			.type = list_option,
-			.name = "Duplex",
-			.err  = "parameter ignored",
-			.def  = 0,
-			.arg  = { .l = { .nr = (int)ARRAY_SIZE(dplx_list),
-					 .p = dplx_list } }
-		};
-		dplx = Duplex;
-		pch_gbe_validate_option(&dplx, &opt, adapter);
-	}
-
-	{ /* Autoneg */
-		static const struct pch_gbe_option opt = {
-			.type = list_option,
-			.name = "AutoNeg",
-			.err  = "parameter ignored",
-			.def  = PCH_AUTONEG_ADVERTISE_DEFAULT,
-			.arg  = { .l = { .nr = (int)ARRAY_SIZE(an_list),
-					 .p = an_list} }
-		};
-		if (speed || dplx) {
-			netdev_dbg(adapter->netdev,
-				   "AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n");
-			hw->phy.autoneg_advertised = opt.def;
-		} else {
-			int tmp = AutoNeg;
-
-			pch_gbe_validate_option(&tmp, &opt, adapter);
-			hw->phy.autoneg_advertised = tmp;
-		}
-	}
-
-	switch (speed + dplx) {
-	case 0:
-		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
-		if ((speed || dplx))
-			netdev_dbg(adapter->netdev,
-				   "Speed and duplex autonegotiation enabled\n");
-		hw->mac.link_speed = SPEED_10;
-		hw->mac.link_duplex = DUPLEX_HALF;
-		break;
-	case HALF_DUPLEX:
-		netdev_dbg(adapter->netdev,
-			   "Half Duplex specified without Speed\n");
-		netdev_dbg(adapter->netdev,
-			   "Using Autonegotiation at Half Duplex only\n");
-		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
-		hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
-						PHY_ADVERTISE_100_HALF;
-		hw->mac.link_speed = SPEED_10;
-		hw->mac.link_duplex = DUPLEX_HALF;
-		break;
-	case FULL_DUPLEX:
-		netdev_dbg(adapter->netdev,
-			   "Full Duplex specified without Speed\n");
-		netdev_dbg(adapter->netdev,
-			   "Using Autonegotiation at Full Duplex only\n");
-		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
-		hw->phy.autoneg_advertised = PHY_ADVERTISE_10_FULL |
-						PHY_ADVERTISE_100_FULL |
-						PHY_ADVERTISE_1000_FULL;
-		hw->mac.link_speed = SPEED_10;
-		hw->mac.link_duplex = DUPLEX_FULL;
-		break;
-	case SPEED_10:
-		netdev_dbg(adapter->netdev,
-			   "10 Mbps Speed specified without Duplex\n");
-		netdev_dbg(adapter->netdev,
-			   "Using Autonegotiation at 10 Mbps only\n");
-		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
-		hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
-						PHY_ADVERTISE_10_FULL;
-		hw->mac.link_speed = SPEED_10;
-		hw->mac.link_duplex = DUPLEX_HALF;
-		break;
-	case SPEED_10 + HALF_DUPLEX:
-		netdev_dbg(adapter->netdev, "Forcing to 10 Mbps Half Duplex\n");
-		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
-		hw->phy.autoneg_advertised = 0;
-		hw->mac.link_speed = SPEED_10;
-		hw->mac.link_duplex = DUPLEX_HALF;
-		break;
-	case SPEED_10 + FULL_DUPLEX:
-		netdev_dbg(adapter->netdev, "Forcing to 10 Mbps Full Duplex\n");
-		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
-		hw->phy.autoneg_advertised = 0;
-		hw->mac.link_speed = SPEED_10;
-		hw->mac.link_duplex = DUPLEX_FULL;
-		break;
-	case SPEED_100:
-		netdev_dbg(adapter->netdev,
-			   "100 Mbps Speed specified without Duplex\n");
-		netdev_dbg(adapter->netdev,
-			   "Using Autonegotiation at 100 Mbps only\n");
-		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
-		hw->phy.autoneg_advertised = PHY_ADVERTISE_100_HALF |
-						PHY_ADVERTISE_100_FULL;
-		hw->mac.link_speed = SPEED_100;
-		hw->mac.link_duplex = DUPLEX_HALF;
-		break;
-	case SPEED_100 + HALF_DUPLEX:
-		netdev_dbg(adapter->netdev,
-			   "Forcing to 100 Mbps Half Duplex\n");
-		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
-		hw->phy.autoneg_advertised = 0;
-		hw->mac.link_speed = SPEED_100;
-		hw->mac.link_duplex = DUPLEX_HALF;
-		break;
-	case SPEED_100 + FULL_DUPLEX:
-		netdev_dbg(adapter->netdev,
-			   "Forcing to 100 Mbps Full Duplex\n");
-		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
-		hw->phy.autoneg_advertised = 0;
-		hw->mac.link_speed = SPEED_100;
-		hw->mac.link_duplex = DUPLEX_FULL;
-		break;
-	case SPEED_1000:
-		netdev_dbg(adapter->netdev,
-			   "1000 Mbps Speed specified without Duplex\n");
-		goto full_duplex_only;
-	case SPEED_1000 + HALF_DUPLEX:
-		netdev_dbg(adapter->netdev,
-			   "Half Duplex is not supported at 1000 Mbps\n");
-		/* fall through */
-	case SPEED_1000 + FULL_DUPLEX:
-full_duplex_only:
-		netdev_dbg(adapter->netdev,
-			   "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
-		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
-		hw->phy.autoneg_advertised = PHY_ADVERTISE_1000_FULL;
-		hw->mac.link_speed = SPEED_1000;
-		hw->mac.link_duplex = DUPLEX_FULL;
-		break;
-	default:
-		BUG();
-	}
-}
-
 /**
  * pch_gbe_check_options - Range Checking for Command Line Parameters
  * @adapter:  Board private structure
@@ -516,6 +253,4 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
 		pch_gbe_validate_option(&tmp, &opt, adapter);
 		hw->mac.fc = tmp;
 	}
-
-	pch_gbe_check_copper_options(adapter);
 }
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
deleted file mode 100644
index a5cad5ea9436..000000000000
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 1999 - 2010 Intel Corporation.
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
- *
- * This code was derived from the Intel e1000e Linux driver.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "pch_gbe.h"
-#include "pch_gbe_phy.h"
-
-#define PHY_MAX_REG_ADDRESS   0x1F	/* 5 bit address bus (0-0x1F) */
-
-/* PHY 1000 MII Register/Bit Definitions */
-/* PHY Registers defined by IEEE */
-#define PHY_CONTROL           0x00  /* Control Register */
-#define PHY_STATUS            0x01  /* Status Regiser */
-#define PHY_ID1               0x02  /* Phy Id Register (word 1) */
-#define PHY_ID2               0x03  /* Phy Id Register (word 2) */
-#define PHY_AUTONEG_ADV       0x04  /* Autoneg Advertisement */
-#define PHY_LP_ABILITY        0x05  /* Link Partner Ability (Base Page) */
-#define PHY_AUTONEG_EXP       0x06  /* Autoneg Expansion Register */
-#define PHY_NEXT_PAGE_TX      0x07  /* Next Page TX */
-#define PHY_LP_NEXT_PAGE      0x08  /* Link Partner Next Page */
-#define PHY_1000T_CTRL        0x09  /* 1000Base-T Control Register */
-#define PHY_1000T_STATUS      0x0A  /* 1000Base-T Status Register */
-#define PHY_EXT_STATUS        0x0F  /* Extended Status Register */
-#define PHY_PHYSP_CONTROL     0x10  /* PHY Specific Control Register */
-#define PHY_EXT_PHYSP_CONTROL 0x14  /* Extended PHY Specific Control Register */
-#define PHY_LED_CONTROL       0x18  /* LED Control Register */
-#define PHY_EXT_PHYSP_STATUS  0x1B  /* Extended PHY Specific Status Register */
-
-/* PHY Control Register */
-#define MII_CR_SPEED_SELECT_MSB 0x0040	/* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_COLL_TEST_ENABLE 0x0080	/* Collision test enable */
-#define MII_CR_FULL_DUPLEX      0x0100	/* FDX =1, half duplex =0 */
-#define MII_CR_RESTART_AUTO_NEG 0x0200	/* Restart auto negotiation */
-#define MII_CR_ISOLATE          0x0400	/* Isolate PHY from MII */
-#define MII_CR_POWER_DOWN       0x0800	/* Power down */
-#define MII_CR_AUTO_NEG_EN      0x1000	/* Auto Neg Enable */
-#define MII_CR_SPEED_SELECT_LSB 0x2000	/* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_LOOPBACK         0x4000	/* 0 = normal, 1 = loopback */
-#define MII_CR_RESET            0x8000	/* 0 = normal, 1 = PHY reset */
-#define MII_CR_SPEED_1000       0x0040
-#define MII_CR_SPEED_100        0x2000
-#define MII_CR_SPEED_10         0x0000
-
-/* PHY Status Register */
-#define MII_SR_EXTENDED_CAPS     0x0001	/* Extended register capabilities */
-#define MII_SR_JABBER_DETECT     0x0002	/* Jabber Detected */
-#define MII_SR_LINK_STATUS       0x0004	/* Link Status 1 = link */
-#define MII_SR_AUTONEG_CAPS      0x0008	/* Auto Neg Capable */
-#define MII_SR_REMOTE_FAULT      0x0010	/* Remote Fault Detect */
-#define MII_SR_AUTONEG_COMPLETE  0x0020	/* Auto Neg Complete */
-#define MII_SR_PREAMBLE_SUPPRESS 0x0040	/* Preamble may be suppressed */
-#define MII_SR_EXTENDED_STATUS   0x0100	/* Ext. status info in Reg 0x0F */
-#define MII_SR_100T2_HD_CAPS     0x0200	/* 100T2 Half Duplex Capable */
-#define MII_SR_100T2_FD_CAPS     0x0400	/* 100T2 Full Duplex Capable */
-#define MII_SR_10T_HD_CAPS       0x0800	/* 10T   Half Duplex Capable */
-#define MII_SR_10T_FD_CAPS       0x1000	/* 10T   Full Duplex Capable */
-#define MII_SR_100X_HD_CAPS      0x2000	/* 100X  Half Duplex Capable */
-#define MII_SR_100X_FD_CAPS      0x4000	/* 100X  Full Duplex Capable */
-#define MII_SR_100T4_CAPS        0x8000	/* 100T4 Capable */
-
-/* AR8031 PHY Debug Registers */
-#define PHY_AR803X_ID           0x00001374
-#define PHY_AR8031_DBG_OFF      0x1D
-#define PHY_AR8031_DBG_DAT      0x1E
-#define PHY_AR8031_SERDES       0x05
-#define PHY_AR8031_HIBERNATE    0x0B
-#define PHY_AR8031_SERDES_TX_CLK_DLY   0x0100 /* TX clock delay of 2.0ns */
-#define PHY_AR8031_PS_HIB_EN           0x8000 /* Hibernate enable */
-
-/* Phy Id Register (word 2) */
-#define PHY_REVISION_MASK        0x000F
-
-/* PHY Specific Control Register */
-#define PHYSP_CTRL_ASSERT_CRS_TX  0x0800
-
-
-/* Default value of PHY register */
-#define PHY_CONTROL_DEFAULT         0x1140 /* Control Register */
-#define PHY_AUTONEG_ADV_DEFAULT     0x01e0 /* Autoneg Advertisement */
-#define PHY_NEXT_PAGE_TX_DEFAULT    0x2001 /* Next Page TX */
-#define PHY_1000T_CTRL_DEFAULT      0x0300 /* 1000Base-T Control Register */
-#define PHY_PHYSP_CONTROL_DEFAULT   0x01EE /* PHY Specific Control Register */
-
-/**
- * pch_gbe_phy_get_id - Retrieve the PHY ID and revision
- * @hw:	       Pointer to the HW structure
- * Returns
- *	0:			Successful.
- *	Negative value:		Failed.
- */
-s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw)
-{
-	struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
-	struct pch_gbe_phy_info *phy = &hw->phy;
-	s32 ret;
-	u16 phy_id1;
-	u16 phy_id2;
-
-	ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID1, &phy_id1);
-	if (ret)
-		return ret;
-	ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID2, &phy_id2);
-	if (ret)
-		return ret;
-	/*
-	 * PHY_ID1: [bit15-0:ID(21-6)]
-	 * PHY_ID2: [bit15-10:ID(5-0)][bit9-4:Model][bit3-0:revision]
-	 */
-	phy->id = (u32)phy_id1;
-	phy->id = ((phy->id << 6) | ((phy_id2 & 0xFC00) >> 10));
-	phy->revision = (u32) (phy_id2 & 0x000F);
-	netdev_dbg(adapter->netdev,
-		   "phy->id : 0x%08x  phy->revision : 0x%08x\n",
-		   phy->id, phy->revision);
-	return 0;
-}
-
-/**
- * pch_gbe_phy_read_reg_miic - Read MII control register
- * @hw:	     Pointer to the HW structure
- * @offset:  Register offset to be read
- * @data:    Pointer to the read data
- * Returns
- *	0:		Successful.
- *	-EINVAL:	Invalid argument.
- */
-s32 pch_gbe_phy_read_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 *data)
-{
-	struct pch_gbe_phy_info *phy = &hw->phy;
-
-	if (offset > PHY_MAX_REG_ADDRESS) {
-		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
-
-		netdev_err(adapter->netdev, "PHY Address %d is out of range\n",
-			   offset);
-		return -EINVAL;
-	}
-	*data = pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_READ,
-				      offset, (u16)0);
-	return 0;
-}
-
-/**
- * pch_gbe_phy_write_reg_miic - Write MII control register
- * @hw:	     Pointer to the HW structure
- * @offset:  Register offset to be read
- * @data:    data to write to register at offset
- * Returns
- *	0:		Successful.
- *	-EINVAL:	Invalid argument.
- */
-s32 pch_gbe_phy_write_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 data)
-{
-	struct pch_gbe_phy_info *phy = &hw->phy;
-
-	if (offset > PHY_MAX_REG_ADDRESS) {
-		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
-
-		netdev_err(adapter->netdev, "PHY Address %d is out of range\n",
-			   offset);
-		return -EINVAL;
-	}
-	pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_WRITE,
-				 offset, data);
-	return 0;
-}
-
-/**
- * pch_gbe_phy_sw_reset - PHY software reset
- * @hw:	            Pointer to the HW structure
- */
-void pch_gbe_phy_sw_reset(struct pch_gbe_hw *hw)
-{
-	u16 phy_ctrl;
-
-	pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &phy_ctrl);
-	phy_ctrl |= MII_CR_RESET;
-	pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, phy_ctrl);
-	udelay(1);
-}
-
-/**
- * pch_gbe_phy_hw_reset - PHY hardware reset
- * @hw:	   Pointer to the HW structure
- */
-void pch_gbe_phy_hw_reset(struct pch_gbe_hw *hw)
-{
-	pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, PHY_CONTROL_DEFAULT);
-	pch_gbe_phy_write_reg_miic(hw, PHY_AUTONEG_ADV,
-					PHY_AUTONEG_ADV_DEFAULT);
-	pch_gbe_phy_write_reg_miic(hw, PHY_NEXT_PAGE_TX,
-					PHY_NEXT_PAGE_TX_DEFAULT);
-	pch_gbe_phy_write_reg_miic(hw, PHY_1000T_CTRL, PHY_1000T_CTRL_DEFAULT);
-	pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL,
-					PHY_PHYSP_CONTROL_DEFAULT);
-}
-
-/**
- * pch_gbe_phy_power_up - restore link in case the phy was powered down
- * @hw:	   Pointer to the HW structure
- */
-void pch_gbe_phy_power_up(struct pch_gbe_hw *hw)
-{
-	u16 mii_reg;
-
-	mii_reg = 0;
-	/* Just clear the power down bit to wake the phy back up */
-	/* according to the manual, the phy will retain its
-	 * settings across a power-down/up cycle */
-	pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
-	mii_reg &= ~MII_CR_POWER_DOWN;
-	pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
-}
-
-/**
- * pch_gbe_phy_power_down - Power down PHY
- * @hw:	   Pointer to the HW structure
- */
-void pch_gbe_phy_power_down(struct pch_gbe_hw *hw)
-{
-	u16 mii_reg;
-
-	mii_reg = 0;
-	/* Power down the PHY so no link is implied when interface is down *
-	 * The PHY cannot be powered down if any of the following is TRUE *
-	 * (a) WoL is enabled
-	 * (b) AMT is active
-	 */
-	pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
-	mii_reg |= MII_CR_POWER_DOWN;
-	pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
-	mdelay(1);
-}
-
-/**
- * pch_gbe_phy_set_rgmii - RGMII interface setting
- * @hw:	            Pointer to the HW structure
- */
-void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw)
-{
-	pch_gbe_phy_sw_reset(hw);
-}
-
-/**
- * pch_gbe_phy_tx_clk_delay - Setup TX clock delay via the PHY
- * @hw:	            Pointer to the HW structure
- * Returns
- *	0:		Successful.
- *	-EINVAL:	Invalid argument.
- */
-static int pch_gbe_phy_tx_clk_delay(struct pch_gbe_hw *hw)
-{
-	/* The RGMII interface requires a ~2ns TX clock delay. This is typically
-	 * done in layout with a longer trace or via PHY strapping, but can also
-	 * be done via PHY configuration registers.
-	 */
-	struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
-	u16 mii_reg;
-	int ret = 0;
-
-	switch (hw->phy.id) {
-	case PHY_AR803X_ID:
-		netdev_dbg(adapter->netdev,
-			   "Configuring AR803X PHY for 2ns TX clock delay\n");
-		pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_OFF, &mii_reg);
-		ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
-						 PHY_AR8031_SERDES);
-		if (ret)
-			break;
-
-		pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
-		mii_reg |= PHY_AR8031_SERDES_TX_CLK_DLY;
-		ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
-						 mii_reg);
-		break;
-	default:
-		netdev_err(adapter->netdev,
-			   "Unknown PHY (%x), could not set TX clock delay\n",
-			   hw->phy.id);
-		return -EINVAL;
-	}
-
-	if (ret)
-		netdev_err(adapter->netdev,
-			   "Could not configure tx clock delay for PHY\n");
-	return ret;
-}
-
-/**
- * pch_gbe_phy_init_setting - PHY initial setting
- * @hw:	            Pointer to the HW structure
- */
-void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw)
-{
-	struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
-	struct ethtool_cmd     cmd = { .cmd = ETHTOOL_GSET };
-	int ret;
-	u16 mii_reg;
-
-	ret = mii_ethtool_gset(&adapter->mii, &cmd);
-	if (ret)
-		netdev_err(adapter->netdev, "Error: mii_ethtool_gset\n");
-
-	ethtool_cmd_speed_set(&cmd, hw->mac.link_speed);
-	cmd.duplex = hw->mac.link_duplex;
-	cmd.advertising = hw->phy.autoneg_advertised;
-	cmd.autoneg = hw->mac.autoneg;
-	pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET);
-	ret = mii_ethtool_sset(&adapter->mii, &cmd);
-	if (ret)
-		netdev_err(adapter->netdev, "Error: mii_ethtool_sset\n");
-
-	pch_gbe_phy_sw_reset(hw);
-
-	pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg);
-	mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX;
-	pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg);
-
-	/* Setup a TX clock delay on certain platforms */
-	if (adapter->pdata && adapter->pdata->phy_tx_clk_delay)
-		pch_gbe_phy_tx_clk_delay(hw);
-}
-
-/**
- * pch_gbe_phy_disable_hibernate - Disable the PHY low power state
- * @hw:	            Pointer to the HW structure
- * Returns
- *	0:		Successful.
- *	-EINVAL:	Invalid argument.
- */
-int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw)
-{
-	struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
-	u16 mii_reg;
-	int ret = 0;
-
-	switch (hw->phy.id) {
-	case PHY_AR803X_ID:
-		netdev_dbg(adapter->netdev,
-			   "Disabling hibernation for AR803X PHY\n");
-		ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
-						 PHY_AR8031_HIBERNATE);
-		if (ret)
-			break;
-
-		pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
-		mii_reg &= ~PHY_AR8031_PS_HIB_EN;
-		ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
-						 mii_reg);
-		break;
-	default:
-		netdev_err(adapter->netdev,
-			   "Unknown PHY (%x), could not disable hibernation\n",
-			   hw->phy.id);
-		return -EINVAL;
-	}
-
-	if (ret)
-		netdev_err(adapter->netdev,
-			   "Could not disable PHY hibernation\n");
-	return ret;
-}
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
deleted file mode 100644
index 95ad0151ad02..000000000000
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 1999 - 2010 Intel Corporation.
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
- *
- * This code was derived from the Intel e1000e Linux driver.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef _PCH_GBE_PHY_H_
-#define _PCH_GBE_PHY_H_
-
-#define PCH_GBE_PHY_REGS_LEN		32
-#define	PCH_GBE_PHY_RESET_DELAY_US	10
-#define PCH_GBE_MAC_IFOP_RGMII
-
-s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw);
-s32 pch_gbe_phy_read_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 *data);
-s32 pch_gbe_phy_write_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 data);
-void pch_gbe_phy_sw_reset(struct pch_gbe_hw *hw);
-void pch_gbe_phy_hw_reset(struct pch_gbe_hw *hw);
-void pch_gbe_phy_power_up(struct pch_gbe_hw *hw);
-void pch_gbe_phy_power_down(struct pch_gbe_hw *hw);
-void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw);
-void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw);
-int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw);
-
-#endif /* _PCH_GBE_PHY_H_ */
-- 
2.17.0

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

* [PATCH v6 3/6] net: pch_gbe: Support DeviceTree for MDIO/PHY description
  2018-05-10 23:16 [PATCH v6 0/6] net: pch_gbe: MIPS support Paul Burton
  2018-05-10 23:16 ` [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask() Paul Burton
  2018-05-10 23:16 ` [PATCH v6 2/6] net: ethernet: pch_gbe: Convert to mdiobus and phylib Paul Burton
@ 2018-05-10 23:16 ` Paul Burton
  2018-05-10 23:16 ` [PATCH v6 4/6] ptp: pch: Allow build on MIPS platforms Paul Burton
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: Paul Burton @ 2018-05-10 23:16 UTC (permalink / raw)
  To: netdev; +Cc: linux-mips, David S . Miller, Andrew Lunn, Paul Burton

When running on a system which uses device tree, use
of_mdiobus_register() rather than plain mdiobus_register() in order to
support parsing PHY information from the DT.

On systems without CONFIG_OF_MDIO set of_mdiobus_register() falls back
to mdiobus_register() anyway, but here we check for a non-NULL device
node in order to continue functioning as-is if a system has
CONFIG_OF_MDIO=y but doesn't use the devicetree.

Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org

---

Changes in v6:
- New patch, significantly simplified by Andrew's preceding patches.

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index b20ed110cdef..f491044c2739 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/at803x_phy.h>
+#include <linux/of_mdio.h>
 
 #define DRV_VERSION     "1.01"
 const char pch_driver_version[] = DRV_VERSION;
@@ -829,6 +830,9 @@ static int pch_gbe_init_mdio(struct pch_gbe_adapter *adapter)
 
 	adapter->mdiobus = bus;
 
+	if (dev->of_node)
+		return of_mdiobus_register(bus, dev->of_node);
+
 	return mdiobus_register(bus);
 }
 
-- 
2.17.0

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

* [PATCH v6 4/6] ptp: pch: Allow build on MIPS platforms
  2018-05-10 23:16 [PATCH v6 0/6] net: pch_gbe: MIPS support Paul Burton
                   ` (2 preceding siblings ...)
  2018-05-10 23:16 ` [PATCH v6 3/6] net: pch_gbe: Support DeviceTree for MDIO/PHY description Paul Burton
@ 2018-05-10 23:16 ` Paul Burton
  2018-05-10 23:16 ` [PATCH v6 5/6] net: pch_gbe: " Paul Burton
  2018-05-10 23:16 ` [PATCH v6 6/6] MIPS: Boston: Adjust DT for pch_gbe PHY support Paul Burton
  5 siblings, 0 replies; 15+ messages in thread
From: Paul Burton @ 2018-05-10 23:16 UTC (permalink / raw)
  To: netdev
  Cc: linux-mips, David S . Miller, Andrew Lunn, Paul Burton, Paul Burton

Allow the ptp_pch driver to be built on MIPS platforms in preparation
for use on the MIPS Boston board.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org

Signed-off-by: Paul Burton <paul.burton@mips.com>
---

Changes in v6: None
Changes in v5:
- Newly included in this series to satisfy Kconfig.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/ptp/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index a21ad10d613c..8618982ab96a 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -90,7 +90,7 @@ config DP83640_PHY
 
 config PTP_1588_CLOCK_PCH
 	tristate "Intel PCH EG20T as PTP clock"
-	depends on X86_32 || COMPILE_TEST
+	depends on X86_32 || MIPS || COMPILE_TEST
 	depends on HAS_IOMEM && NET
 	imply PTP_1588_CLOCK
 	help
-- 
2.17.0

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

* [PATCH v6 5/6] net: pch_gbe: Allow build on MIPS platforms
  2018-05-10 23:16 [PATCH v6 0/6] net: pch_gbe: MIPS support Paul Burton
                   ` (3 preceding siblings ...)
  2018-05-10 23:16 ` [PATCH v6 4/6] ptp: pch: Allow build on MIPS platforms Paul Burton
@ 2018-05-10 23:16 ` Paul Burton
  2018-05-10 23:16 ` [PATCH v6 6/6] MIPS: Boston: Adjust DT for pch_gbe PHY support Paul Burton
  5 siblings, 0 replies; 15+ messages in thread
From: Paul Burton @ 2018-05-10 23:16 UTC (permalink / raw)
  To: netdev; +Cc: linux-mips, David S . Miller, Andrew Lunn, Paul Burton

Allow the pch_gbe driver to be built on MIPS platforms, allowing its use
on the MIPS Boston development board.

Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org

---

Changes in v6:
- None.

Changes in v5:
- None.

Changes in v4:
- None.

Changes in v3:
- None.

Changes in v2:
- None.

 drivers/net/ethernet/oki-semi/pch_gbe/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
index 045256e99586..bf85c44fb7e5 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
@@ -4,7 +4,7 @@
 
 config PCH_GBE
 	tristate "OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE"
-	depends on PCI && (X86_32 || COMPILE_TEST)
+	depends on PCI && (X86_32 || MIPS || COMPILE_TEST)
 	select PTP_1588_CLOCK_PCH
 	select NET_PTP_CLASSIFY
 	select AT803X_PHY
-- 
2.17.0

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

* [PATCH v6 6/6] MIPS: Boston: Adjust DT for pch_gbe PHY support
  2018-05-10 23:16 [PATCH v6 0/6] net: pch_gbe: MIPS support Paul Burton
                   ` (4 preceding siblings ...)
  2018-05-10 23:16 ` [PATCH v6 5/6] net: pch_gbe: " Paul Burton
@ 2018-05-10 23:16 ` Paul Burton
  2018-05-11  0:28   ` Andrew Lunn
  2018-05-11  0:35   ` Andrew Lunn
  5 siblings, 2 replies; 15+ messages in thread
From: Paul Burton @ 2018-05-10 23:16 UTC (permalink / raw)
  To: netdev; +Cc: linux-mips, David S . Miller, Andrew Lunn, Paul Burton

The pch_gbe driver support for PHY reset GPIOs is now provided by the
standard phylib infrastructure, using a standard PHY binding. Adjust the
Boston devicetree to make use of the standard PHY binding.

This is possible because we bundle the DT along with the kernel binary
into a Flattened Image Tree, so the DT and kernel are always shipped
together for the Boston platform.

Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org

---

Changes in v6:
- New patch.

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/mips/boot/dts/img/boston.dts | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/mips/boot/dts/img/boston.dts b/arch/mips/boot/dts/img/boston.dts
index 65af3f6ba81c..cb55f7ba20c3 100644
--- a/arch/mips/boot/dts/img/boston.dts
+++ b/arch/mips/boot/dts/img/boston.dts
@@ -144,8 +144,17 @@
 				eg20t_mac@2,0,1 {
 					compatible = "pci8086,8802";
 					reg = <0x00020100 0 0 0 0>;
-					phy-reset-gpios = <&eg20t_gpio 6
-							   GPIO_ACTIVE_LOW>;
+
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					ethernet-phy@0 {
+						compatible = "ethernet-phy-id001c.c915";
+						reg = <0>;
+						reset-gpios = <&eg20t_gpio 6 GPIO_ACTIVE_LOW>;
+						reset-assert-us = <25000>;
+						reset-deassert-us = <25000>;
+					};
 				};
 
 				eg20t_gpio: eg20t_gpio@2,0,2 {
-- 
2.17.0

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

* Re: [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask()
  2018-05-10 23:16 ` [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask() Paul Burton
@ 2018-05-11  0:26   ` Andrew Lunn
  2018-05-11 18:25     ` Paul Burton
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Lunn @ 2018-05-11  0:26 UTC (permalink / raw)
  To: Paul Burton; +Cc: netdev, linux-mips, David S . Miller

On Thu, May 10, 2018 at 04:16:52PM -0700, Paul Burton wrote:
> From: Andrew Lunn <andrew@lunn.ch>
> 
> On some boards, this PHY has a problem when it hibernates. Export this
> function to a board can register a PHY fixup to disable hibernation.

What do you know about the problem?

https://patchwork.ozlabs.org/patch/686371/

I don't remember how it was solved, but you should probably do the
same.

	Andrew

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

* Re: [PATCH v6 6/6] MIPS: Boston: Adjust DT for pch_gbe PHY support
  2018-05-10 23:16 ` [PATCH v6 6/6] MIPS: Boston: Adjust DT for pch_gbe PHY support Paul Burton
@ 2018-05-11  0:28   ` Andrew Lunn
  2018-05-11  0:35   ` Andrew Lunn
  1 sibling, 0 replies; 15+ messages in thread
From: Andrew Lunn @ 2018-05-11  0:28 UTC (permalink / raw)
  To: Paul Burton; +Cc: netdev, linux-mips, David S . Miller

> +					ethernet-phy@0 {
> +						compatible = "ethernet-phy-id001c.c915";

You only need to specify the compatible string like this if the PHY
has its own ID wrong. The AT802x gets this right, so you don't need
this.

	Andrew

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

* Re: [PATCH v6 6/6] MIPS: Boston: Adjust DT for pch_gbe PHY support
  2018-05-10 23:16 ` [PATCH v6 6/6] MIPS: Boston: Adjust DT for pch_gbe PHY support Paul Burton
  2018-05-11  0:28   ` Andrew Lunn
@ 2018-05-11  0:35   ` Andrew Lunn
  1 sibling, 0 replies; 15+ messages in thread
From: Andrew Lunn @ 2018-05-11  0:35 UTC (permalink / raw)
  To: Paul Burton; +Cc: netdev, linux-mips, David S . Miller

>  				eg20t_mac@2,0,1 {
>  					compatible = "pci8086,8802";
>  					reg = <0x00020100 0 0 0 0>;
> -					phy-reset-gpios = <&eg20t_gpio 6
> -							   GPIO_ACTIVE_LOW>;
> +
> +					#address-cells = <1>;
> +					#size-cells = <0>;

It is generally a good idea to put an 'mdio' container which the PHYs
are on. You then pass this container node to of_mdiobus_register().

> +
> +					ethernet-phy@0 {
> +						compatible = "ethernet-phy-id001c.c915";
> +						reg = <0>;
> +						reset-gpios = <&eg20t_gpio 6 GPIO_ACTIVE_LOW>;
> +						reset-assert-us = <25000>;
> +						reset-deassert-us = <25000>;
> +					};

  Andrew

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

* Re: [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask()
  2018-05-11  0:26   ` Andrew Lunn
@ 2018-05-11 18:25     ` Paul Burton
  2018-05-11 18:38       ` Paul Burton
  2018-05-11 19:24       ` Andrew Lunn
  0 siblings, 2 replies; 15+ messages in thread
From: Paul Burton @ 2018-05-11 18:25 UTC (permalink / raw)
  To: Andrew Lunn, Darren Hart; +Cc: netdev, linux-mips, David S . Miller

Hi Andrew,

On Fri, May 11, 2018 at 02:26:19AM +0200, Andrew Lunn wrote:
> On Thu, May 10, 2018 at 04:16:52PM -0700, Paul Burton wrote:
> > From: Andrew Lunn <andrew@lunn.ch>
> > 
> > On some boards, this PHY has a problem when it hibernates. Export this
> > function to a board can register a PHY fixup to disable hibernation.
> 
> What do you know about the problem?
> 
> https://patchwork.ozlabs.org/patch/686371/
> 
> I don't remember how it was solved, but you should probably do the
> same.
> 
> 	Andrew

I'm afraid I don't know much about the problem - this one is your patch
entirely unchanged, and I don't have access to the hardware in question
(my board uses a Realtek RTL8211E PHY).

I presume you did this because the pch_gbe driver as-is in mainline
disables hibernation for the AR803X PHY found on the MinnowBoard, so
this would be preserving the existing behaviour of the driver?

That behaviour was introduced by commit f1a26fdf5944f ("pch_gbe: Add
MinnowBoard support"), so perhaps Darren as its author might know more?

My presumption would be that this is done to ensure that the PHY is
always providing the RX clock, which the EG20T manual says is required
for the MAC reset register RX_RST & ALL_RST bits to clear. We wait for
those using the call to pch_gbe_wait_clr_bit() in
pch_gbe_mac_reset_hw(), which happens before we initialize the PHY.

I could reorder the probe function a little to initialize the PHY before
performing the MAC reset, drop this patch and the AR803X hibernation
stuff from patch 2 if you like. But again, I can't actually test the
result on the affected hardware.

Thanks,
    Paul

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

* Re: [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask()
  2018-05-11 18:25     ` Paul Burton
@ 2018-05-11 18:38       ` Paul Burton
  2018-05-11 19:24       ` Andrew Lunn
  1 sibling, 0 replies; 15+ messages in thread
From: Paul Burton @ 2018-05-11 18:38 UTC (permalink / raw)
  To: Andrew Lunn, Darren Hart; +Cc: netdev, linux-mips, David S . Miller

On Fri, May 11, 2018 at 11:25:02AM -0700, Paul Burton wrote:
> Hi Andrew,
> 
> On Fri, May 11, 2018 at 02:26:19AM +0200, Andrew Lunn wrote:
> > On Thu, May 10, 2018 at 04:16:52PM -0700, Paul Burton wrote:
> > > From: Andrew Lunn <andrew@lunn.ch>
> > > 
> > > On some boards, this PHY has a problem when it hibernates. Export this
> > > function to a board can register a PHY fixup to disable hibernation.
> > 
> > What do you know about the problem?
> > 
> > https://patchwork.ozlabs.org/patch/686371/
> > 
> > I don't remember how it was solved, but you should probably do the
> > same.
> > 
> > 	Andrew
> 
> I'm afraid I don't know much about the problem - this one is your patch
> entirely unchanged, and I don't have access to the hardware in question
> (my board uses a Realtek RTL8211E PHY).
> 
> I presume you did this because the pch_gbe driver as-is in mainline
> disables hibernation for the AR803X PHY found on the MinnowBoard, so
> this would be preserving the existing behaviour of the driver?
> 
> That behaviour was introduced by commit f1a26fdf5944f ("pch_gbe: Add
> MinnowBoard support"), so perhaps Darren as its author might know more?
> 
> My presumption would be that this is done to ensure that the PHY is
> always providing the RX clock, which the EG20T manual says is required
> for the MAC reset register RX_RST & ALL_RST bits to clear. We wait for
> those using the call to pch_gbe_wait_clr_bit() in
> pch_gbe_mac_reset_hw(), which happens before we initialize the PHY.
> 
> I could reorder the probe function a little to initialize the PHY before
> performing the MAC reset, drop this patch and the AR803X hibernation
> stuff from patch 2 if you like. But again, I can't actually test the
> result on the affected hardware.
> 
> Thanks,
>     Paul

I got an undeliverable response using Darren's email address from the
commit referenced above, so updating to the latest address I see for him
in git history.

Thanks,
    Paul

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

* Re: [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask()
  2018-05-11 18:25     ` Paul Burton
  2018-05-11 18:38       ` Paul Burton
@ 2018-05-11 19:24       ` Andrew Lunn
  2018-05-11 22:22         ` Paul Burton
  1 sibling, 1 reply; 15+ messages in thread
From: Andrew Lunn @ 2018-05-11 19:24 UTC (permalink / raw)
  To: Paul Burton; +Cc: Darren Hart, netdev, linux-mips, David S . Miller

> I could reorder the probe function a little to initialize the PHY before
> performing the MAC reset, drop this patch and the AR803X hibernation
> stuff from patch 2 if you like. But again, I can't actually test the
> result on the affected hardware.

Hi Paul

I don't like a MAC driver poking around in PHY registers.

So if you can rearrange the code, that would be great.

   Thanks
	Andrew

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

* Re: [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask()
  2018-05-11 19:24       ` Andrew Lunn
@ 2018-05-11 22:22         ` Paul Burton
  2018-05-12 21:37           ` Andrew Lunn
  0 siblings, 1 reply; 15+ messages in thread
From: Paul Burton @ 2018-05-11 22:22 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: Darren Hart, netdev, linux-mips, David S . Miller

Hi Andrew,

On Fri, May 11, 2018 at 09:24:46PM +0200, Andrew Lunn wrote:
> > I could reorder the probe function a little to initialize the PHY before
> > performing the MAC reset, drop this patch and the AR803X hibernation
> > stuff from patch 2 if you like. But again, I can't actually test the
> > result on the affected hardware.
> 
> Hi Paul
> 
> I don't like a MAC driver poking around in PHY registers.
> 
> So if you can rearrange the code, that would be great.
> 
>    Thanks
> 	Andrew

Sure, I'll give it a shot.

After digging into it I see 2 ways to go here:

  1) We could just always reset the PHY before we reset the MAC. That
     would give us a window of however long the PHY takes to enter its
     low power state & stop providing the RX clock during which we'd
     need the MAC reset to complete. In the case of the AR8031 that's
     "about 10 seconds" according to its data sheet. In this particular
     case that feels like plenty, but it does also feel a bit icky to
     rely on the timing chosen by the PHY manufacturer to line up with
     that of the MAC reset.

  2) We could introduce a couple of new phy_* functions to disable &
     enable low power states like the AR8031's hibernation feature, by
     calling new function pointers in struct phy_driver. Then pch_gbe &
     other MACs could call those to have the PHY driver disable
     hibernation at times where we know we'll need the RX clock and
     re-enable it afterwards.

I'm currently leaning towards option 2. How does that sound to you? Or
can you see another way to handle this?

Thanks,
    Paul

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

* Re: [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask()
  2018-05-11 22:22         ` Paul Burton
@ 2018-05-12 21:37           ` Andrew Lunn
  0 siblings, 0 replies; 15+ messages in thread
From: Andrew Lunn @ 2018-05-12 21:37 UTC (permalink / raw)
  To: Paul Burton; +Cc: Darren Hart, netdev, linux-mips, David S . Miller

On Fri, May 11, 2018 at 03:22:39PM -0700, Paul Burton wrote:
> Hi Andrew,
> 
> On Fri, May 11, 2018 at 09:24:46PM +0200, Andrew Lunn wrote:
> > > I could reorder the probe function a little to initialize the PHY before
> > > performing the MAC reset, drop this patch and the AR803X hibernation
> > > stuff from patch 2 if you like. But again, I can't actually test the
> > > result on the affected hardware.
> > 
> > Hi Paul
> > 
> > I don't like a MAC driver poking around in PHY registers.
> > 
> > So if you can rearrange the code, that would be great.
> > 
> >    Thanks
> > 	Andrew
> 
> Sure, I'll give it a shot.
> 
> After digging into it I see 2 ways to go here:
> 
>   1) We could just always reset the PHY before we reset the MAC. That
>      would give us a window of however long the PHY takes to enter its
>      low power state & stop providing the RX clock during which we'd
>      need the MAC reset to complete. In the case of the AR8031 that's
>      "about 10 seconds" according to its data sheet. In this particular
>      case that feels like plenty, but it does also feel a bit icky to
>      rely on the timing chosen by the PHY manufacturer to line up with
>      that of the MAC reset.
> 
>   2) We could introduce a couple of new phy_* functions to disable &
>      enable low power states like the AR8031's hibernation feature, by
>      calling new function pointers in struct phy_driver. Then pch_gbe &
>      other MACs could call those to have the PHY driver disable
>      hibernation at times where we know we'll need the RX clock and
>      re-enable it afterwards.

Hi Paul

When there is no link, you don't need the MAC running. My assumption
is that the PHY is designed around that idea, you leave the MAC idle
until there is a link. When the phylib calls the link_change handler,
the MAC should then be started/stopped depending on the state of the
link. You are then guaranteed to have the clock when you need it.

I've no idea how easy this is to implement given the current code...

     Andrew

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

end of thread, other threads:[~2018-05-12 21:37 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-10 23:16 [PATCH v6 0/6] net: pch_gbe: MIPS support Paul Burton
2018-05-10 23:16 ` [PATCH v6 1/6] net: phy: at803x: Export at803x_debug_reg_mask() Paul Burton
2018-05-11  0:26   ` Andrew Lunn
2018-05-11 18:25     ` Paul Burton
2018-05-11 18:38       ` Paul Burton
2018-05-11 19:24       ` Andrew Lunn
2018-05-11 22:22         ` Paul Burton
2018-05-12 21:37           ` Andrew Lunn
2018-05-10 23:16 ` [PATCH v6 2/6] net: ethernet: pch_gbe: Convert to mdiobus and phylib Paul Burton
2018-05-10 23:16 ` [PATCH v6 3/6] net: pch_gbe: Support DeviceTree for MDIO/PHY description Paul Burton
2018-05-10 23:16 ` [PATCH v6 4/6] ptp: pch: Allow build on MIPS platforms Paul Burton
2018-05-10 23:16 ` [PATCH v6 5/6] net: pch_gbe: " Paul Burton
2018-05-10 23:16 ` [PATCH v6 6/6] MIPS: Boston: Adjust DT for pch_gbe PHY support Paul Burton
2018-05-11  0:28   ` Andrew Lunn
2018-05-11  0:35   ` Andrew Lunn

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.