All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roelof Berg <rberg@berg-solutions.de>
To: rberg@berg-solutions.de
Cc: andrew@lunn.ch, Bryan Whitehead <bryan.whitehead@microchip.com>,
	Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>,
	"David S. Miller" <davem@davemloft.net>,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] lan743x: Added fixed link support
Date: Wed, 13 May 2020 21:06:33 +0200	[thread overview]
Message-ID: <20200513190633.7815-1-rberg@berg-solutions.de> (raw)

Microchip lan7431 is frequently connected to a phy. However, it
can also be directly connected to a MII remote peer without
any phy in between. For supporting such a phyless hardware setup
in Linux we added the capability to the driver to understand
the fixed-link and the phy-connection-type entries in the device
tree.

If a fixed-link node is configured in the device tree the lan7431
device will deactivate auto negotiation and uses the speed and
duplex settings configured in the fixed-link node.

Also the phy-connection-type can be configured in the device tree
and in case of a fixed-link connection the RGMII mode can be
configured, all other modes fall back to the default: GMII.

Example:

 &pcie {
	status = "okay";

	host@0 {
		reg = <0 0 0 0 0>;

		#address-cells = <3>;
		#size-cells = <2>;

		ethernet@0 {
			compatible = "weyland-yutani,noscom1", "microchip,lan743x";
			status = "okay";
			reg = <0 0 0 0 0>;
			phy-connection-type = "rgmii";

			fixed-link {
				speed = <100>;
				full-duplex;
			};
		};
	};
};

Signed-off-by: Roelof Berg <rberg@berg-solutions.de>
---
 drivers/net/ethernet/microchip/lan743x_main.c | 94 +++++++++++++++++--
 drivers/net/ethernet/microchip/lan743x_main.h |  4 +
 2 files changed, 89 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index a43140f7b5eb..85f12881340b 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -9,9 +9,12 @@
 #include <linux/microchipphy.h>
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
+#include <linux/phy_fixed.h>
 #include <linux/rtnetlink.h>
 #include <linux/iopoll.h>
 #include <linux/crc16.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
 #include "lan743x_main.h"
 #include "lan743x_ethtool.h"
 
@@ -974,6 +977,8 @@ static void lan743x_phy_close(struct lan743x_adapter *adapter)
 
 	phy_stop(netdev->phydev);
 	phy_disconnect(netdev->phydev);
+	if (of_phy_is_fixed_link(adapter->pdev->dev.of_node))
+		of_phy_deregister_fixed_link(adapter->pdev->dev.of_node);
 	netdev->phydev = NULL;
 }
 
@@ -982,18 +987,86 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
 	struct lan743x_phy *phy = &adapter->phy;
 	struct phy_device *phydev;
 	struct net_device *netdev;
+	struct device_node *phynode;
+	u32 data;
+	phy_interface_t phyifc = PHY_INTERFACE_MODE_GMII;
+	bool fixed_link = false;
 	int ret = -EIO;
 
 	netdev = adapter->netdev;
-	phydev = phy_find_first(adapter->mdiobus);
-	if (!phydev)
-		goto return_error;
+	phynode = of_node_get(adapter->pdev->dev.of_node);
+	if (phynode)
+		of_get_phy_mode(phynode, &phyifc);
+
+	/* check if a fixed-link is defined in device-tree */
+	if (phynode && of_phy_is_fixed_link(phynode)) {
+		fixed_link = true;
+		netdev_dbg(netdev, "fixed-link detected\n");
+
+		ret = of_phy_register_fixed_link(phynode);
+		if (ret) {
+			netdev_err(netdev, "cannot register fixed PHY\n");
+			goto return_error;
+		}
 
-	ret = phy_connect_direct(netdev, phydev,
-				 lan743x_phy_link_status_change,
-				 PHY_INTERFACE_MODE_GMII);
-	if (ret)
-		goto return_error;
+		phydev = of_phy_connect(netdev, phynode,
+					lan743x_phy_link_status_change,
+					0, phyifc);
+		if (!phydev)
+			goto return_error;
+
+		/* Configure MAC to fixed link parameters */
+		data = lan743x_csr_read(adapter, MAC_CR);
+		/* Disable auto negotiation */
+		data &= ~(MAC_CR_ADD_ | MAC_CR_ASD_);
+		/* Set duplex mode */
+		if (phydev->duplex)
+			data |= MAC_CR_DPX_;
+		else
+			data &= ~MAC_CR_DPX_;
+		/* Set bus speed */
+		switch (phydev->speed) {
+		case 10:
+			data &= ~MAC_CR_CFG_H_;
+			data &= ~MAC_CR_CFG_L_;
+			break;
+		case 100:
+			data &= ~MAC_CR_CFG_H_;
+			data |= MAC_CR_CFG_L_;
+			break;
+		case 1000:
+			data |= MAC_CR_CFG_H_;
+			data |= MAC_CR_CFG_L_;
+			break;
+		}
+		/* Set interface mode */
+		if (phyifc == PHY_INTERFACE_MODE_RGMII ||
+		    phyifc == PHY_INTERFACE_MODE_RGMII_ID ||
+		    phyifc == PHY_INTERFACE_MODE_RGMII_RXID ||
+		    phyifc == PHY_INTERFACE_MODE_RGMII_TXID)
+			/* RGMII */
+			data &= ~MAC_CR_MII_EN_;
+		else
+			/* GMII */
+			data |= MAC_CR_MII_EN_;
+		lan743x_csr_write(adapter, MAC_CR, data);
+	} else {
+		phydev = phy_find_first(adapter->mdiobus);
+		if (!phydev)
+			goto return_error;
+
+		ret = phy_connect_direct(netdev, phydev,
+					 lan743x_phy_link_status_change,
+					 PHY_INTERFACE_MODE_GMII);
+		/* Note: We cannot use phyifc here because this would be SGMII
+		 * on a standard PC.
+		 */
+		if (ret)
+			goto return_error;
+	}
+
+	if (phynode)
+		of_node_put(phynode);
 
 	/* MAC doesn't support 1000T Half */
 	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
@@ -1004,10 +1077,13 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
 	phy->fc_autoneg = phydev->autoneg;
 
 	phy_start(phydev);
-	phy_start_aneg(phydev);
+	if (!fixed_link)
+		phy_start_aneg(phydev);
 	return 0;
 
 return_error:
+	if (phynode)
+		of_node_put(phynode);
 	return ret;
 }
 
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 3b02eeae5f45..e49f6b6cd440 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -104,10 +104,14 @@
 	((value << 0) & FCT_FLOW_CTL_ON_THRESHOLD_)
 
 #define MAC_CR				(0x100)
+#define MAC_CR_MII_EN_			BIT(19)
 #define MAC_CR_EEE_EN_			BIT(17)
 #define MAC_CR_ADD_			BIT(12)
 #define MAC_CR_ASD_			BIT(11)
 #define MAC_CR_CNTR_RST_		BIT(5)
+#define MAC_CR_DPX_			BIT(3)
+#define MAC_CR_CFG_H_			BIT(2)
+#define MAC_CR_CFG_L_			BIT(1)
 #define MAC_CR_RST_			BIT(0)
 
 #define MAC_RX				(0x104)
-- 
2.20.1


             reply	other threads:[~2020-05-13 19:07 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-13 19:06 Roelof Berg [this message]
2020-05-13 19:17 ` [PATCH] lan743x: Added fixed link support Florian Fainelli
2020-05-16 19:24 Roelof Berg
2020-05-17 18:37 ` Andrew Lunn
2020-05-17 20:44   ` Roelof Berg
2020-05-17 23:50     ` Andrew Lunn
2020-05-18 19:31       ` Roelof Berg
2020-05-18 20:34         ` Andrew Lunn
2020-05-19 16:42           ` Roelof Berg
2020-05-19 22:06             ` Ronnie.Kunin
2020-05-18 20:53     ` Bryan.Whitehead
2020-05-18 20:01   ` Roelof Berg
2020-05-20 17:10 Roelof Berg
2020-05-21 14:04 ` Andrew Lunn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200513190633.7815-1-rberg@berg-solutions.de \
    --to=rberg@berg-solutions.de \
    --cc=UNGLinuxDriver@microchip.com \
    --cc=andrew@lunn.ch \
    --cc=bryan.whitehead@microchip.com \
    --cc=davem@davemloft.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.