From 04373c37df836557ae7ebb769383baa1b57c5ffa Mon Sep 17 00:00:00 2001
From: Calvin Johnson <calvin.johnson@nxp.com>
Date: Thu, 4 Oct 2018 09:38:17 +0530
Subject: [PATCH] staging: fsl_ppfe/eth: add fixed-link support

In cases where MAC is not connected to a normal MDIO-managed PHY
device, and instead to a switch, it is configured as a "fixed-link".
Code to handle this scenario is added here.

phy_node in the dtb is checked to identify a fixed-link.
On identification of a fixed-link, it is registered and connected.

Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com>
---
 drivers/staging/fsl_ppfe/pfe_eth.c              | 21 ++++++++++++++++++++-
 drivers/staging/fsl_ppfe/pfe_eth.h              |  2 ++
 drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c |  4 ++++
 3 files changed, 26 insertions(+), 1 deletion(-)

--- a/drivers/staging/fsl_ppfe/pfe_eth.c
+++ b/drivers/staging/fsl_ppfe/pfe_eth.c
@@ -39,6 +39,9 @@
 #include <net/ip.h>
 #include <net/sock.h>
 
+#include <linux/of.h>
+#include <linux/of_mdio.h>
+
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <linux/delay.h>
@@ -1263,6 +1266,8 @@ static int pfe_phy_init(struct net_devic
 	char phy_id[MII_BUS_ID_SIZE + 3];
 	char bus_id[MII_BUS_ID_SIZE];
 	phy_interface_t interface;
+	struct device_node *phy_node;
+	int rc;
 
 	priv->oldlink = 0;
 	priv->oldspeed = 0;
@@ -1293,7 +1298,20 @@ static int pfe_phy_init(struct net_devic
 	priv->oldspeed = 0;
 	priv->oldduplex = -1;
 	pr_info("%s interface %x\n", __func__, interface);
-	phydev = phy_connect(ndev, phy_id, &pfe_eth_adjust_link, interface);
+
+	if (of_phy_is_fixed_link(priv->phy_node)) {
+		rc = of_phy_register_fixed_link(priv->phy_node);
+		if (rc)
+			return rc;
+		phy_node = of_node_get(priv->phy_node);
+		phydev = of_phy_connect(ndev, phy_node, pfe_eth_adjust_link, 0,
+					priv->einfo->mii_config);
+		of_node_put(phy_node);
+
+	} else {
+		phydev = phy_connect(ndev, phy_id,
+				     &pfe_eth_adjust_link, interface);
+	}
 
 	if (IS_ERR(phydev)) {
 		netdev_err(ndev, "phy_connect() failed\n");
@@ -2371,6 +2389,7 @@ static int pfe_eth_init_one(struct pfe *
 	priv->ndev = ndev;
 	priv->id = einfo[id].gem_id;
 	priv->pfe = pfe;
+	priv->phy_node = einfo[id].phy_node;
 
 	SET_NETDEV_DEV(priv->ndev, priv->pfe->dev);
 
--- a/drivers/staging/fsl_ppfe/pfe_eth.h
+++ b/drivers/staging/fsl_ppfe/pfe_eth.h
@@ -61,6 +61,7 @@ struct ls1012a_eth_platform_data {
 	u32 phy_id;
 	u32 mdio_muxval;
 	u8 mac_addr[ETH_ALEN];
+	struct device_node	*phy_node;
 };
 
 struct ls1012a_mdio_platform_data {
@@ -144,6 +145,7 @@ struct  pfe_eth_priv_s {
 	int			oldspeed;
 	int			oldduplex;
 	int			oldlink;
+	struct device_node	*phy_node;
 	/* mdio info */
 	int			mdc_div;
 	struct mii_bus		*mii_bus;
--- a/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c
+++ b/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c
@@ -18,8 +18,10 @@
 
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/of.h>
 #include <linux/of_net.h>
 #include <linux/of_address.h>
+#include <linux/of_mdio.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
@@ -118,6 +120,8 @@ static int pfe_get_gemac_if_proprties(st
 	pdata->ls1012a_mdio_pdata[port].irq[0] = PHY_POLL;
 
 done:
+	if (of_phy_is_fixed_link(gem))
+		pdata->ls1012a_eth_pdata[port].phy_node = of_node_get(gem);
 
 	return 0;
 
