linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sergej Bauer <sbauer@blackbox.su>
To: netdev@vger.kernel.org
Cc: andrew@lunn.ch, f.fainelli@gmail.com, sbauer@blackbox.su,
	"David S. Miller" <davem@davemloft.net>,
	Jakub Kicinski <kuba@kernel.org>,
	Bryan Whitehead <bryan.whitehead@microchip.com>,
	UNGLinuxDriver@microchip.com,
	Simon Horman <simon.horman@netronome.com>,
	Mark Einon <mark.einon@gmail.com>,
	Madalin Bucur <madalin.bucur@oss.nxp.com>,
	Arnd Bergmann <arnd@arndb.de>,
	Masahiro Yamada <masahiroy@kernel.org>,
	linux-kernel@vger.kernel.org
Subject: [PATCH v2] lan743x: add virtual PHY for PHY-less devices
Date: Sat, 23 Jan 2021 00:42:41 +0300	[thread overview]
Message-ID: <20210122214247.6536-1-sbauer@blackbox.su> (raw)

From: sbauer@blackbox.su

v1->v2:
	switch to using of fixed_phy as was suggested by Andrew and Florian
	also features-related parts are removed

Previous versions can be found at:
v1:
initial version
	https://lkml.org/lkml/2020/9/17/1272

Signed-off-by: Sergej Bauer <sbauer@blackbox.su>

diff --git a/MAINTAINERS b/MAINTAINERS
index 650deb973913..86304efd7691 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11699,6 +11699,12 @@ L:	netdev@vger.kernel.org
 S:	Maintained
 F:	drivers/net/ethernet/microchip/lan743x_*
 
+MICROCHIP LAN743X VIRTUAL PHY
+M:	Sergej Bauer <sbauer@blackbox.su>
+L:	netdev@vger.kernel.org
+S:	Maintained
+F:	drivers/net/ethernet/microchip/lan743x_virtual_phy.*
+
 MICROCHIP LCDFB DRIVER
 M:	Nicolas Ferre <nicolas.ferre@microchip.com>
 L:	linux-fbdev@vger.kernel.org
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
index d0f6dfe0dcf3..fbc94cf115bd 100644
--- a/drivers/net/ethernet/microchip/Kconfig
+++ b/drivers/net/ethernet/microchip/Kconfig
@@ -48,6 +48,7 @@ config LAN743X
 	select PHYLIB
 	select CRC16
 	select CRC32
+	select FIXED_PHY
 	help
 	  Support for the Microchip LAN743x PCI Express Gigabit Ethernet chip
 
diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile
index da603540ca57..dc3a2d66c286 100644
--- a/drivers/net/ethernet/microchip/Makefile
+++ b/drivers/net/ethernet/microchip/Makefile
@@ -7,4 +7,4 @@ obj-$(CONFIG_ENC28J60) += enc28j60.o
 obj-$(CONFIG_ENCX24J600) += encx24j600.o encx24j600-regmap.o
 obj-$(CONFIG_LAN743X) += lan743x.o
 
-lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o
+lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o lan743x_virtual_phy.o
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index c5de8f46cdd3..22636366d0db 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -816,6 +816,17 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev,
 }
 #endif /* CONFIG_PM */
 
+int lan743x_set_link_ksettings(struct net_device *netdev,
+			       const struct ethtool_link_ksettings *cmd)
+{
+	if (!netdev->phydev)
+		return -ENETDOWN;
+
+	return phy_is_pseudo_fixed_link(netdev->phydev) ?
+			lan743x_set_virtual_link_ksettings(netdev, cmd)
+			: phy_ethtool_set_link_ksettings(netdev, cmd);
+}
+
 const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_drvinfo = lan743x_ethtool_get_drvinfo,
 	.get_msglevel = lan743x_ethtool_get_msglevel,
@@ -839,7 +850,7 @@ const struct ethtool_ops lan743x_ethtool_ops = {
 	.get_eee = lan743x_ethtool_get_eee,
 	.set_eee = lan743x_ethtool_set_eee,
 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
-	.set_link_ksettings = phy_ethtool_set_link_ksettings,
+	.set_link_ksettings = lan743x_set_link_ksettings,
 #ifdef CONFIG_PM
 	.get_wol = lan743x_ethtool_get_wol,
 	.set_wol = lan743x_ethtool_set_wol,
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.h b/drivers/net/ethernet/microchip/lan743x_ethtool.h
index d0d11a777a58..7287474d4a5c 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.h
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.h
@@ -8,4 +8,7 @@
 
 extern const struct ethtool_ops lan743x_ethtool_ops;
 
+int lan743x_set_virtual_link_ksettings(struct net_device *netdev,
+				       const struct ethtool_link_ksettings *cmd);
+
 #endif /* _LAN743X_ETHTOOL_H */
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 3804310c853a..d8c00fa298d0 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -17,6 +17,11 @@
 #include <linux/crc16.h>
 #include "lan743x_main.h"
 #include "lan743x_ethtool.h"
+#include "lan743x_virtual_phy.h"
+
+static char *mii_regs[32];
+static int mii_regs_count;
+module_param_array(mii_regs, charp, &mii_regs_count, 0644);
 
 static void lan743x_pci_cleanup(struct lan743x_adapter *adapter)
 {
@@ -821,7 +826,7 @@ static int lan743x_mac_init(struct lan743x_adapter *adapter)
 	return 0;
 }
 
-static int lan743x_mac_open(struct lan743x_adapter *adapter)
+int lan743x_mac_open(struct lan743x_adapter *adapter)
 {
 	u32 temp;
 
@@ -832,7 +837,7 @@ static int lan743x_mac_open(struct lan743x_adapter *adapter)
 	return 0;
 }
 
-static void lan743x_mac_close(struct lan743x_adapter *adapter)
+void lan743x_mac_close(struct lan743x_adapter *adapter)
 {
 	u32 temp;
 
@@ -1000,8 +1005,10 @@ static void lan743x_phy_close(struct lan743x_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 
 	phy_stop(netdev->phydev);
-	phy_disconnect(netdev->phydev);
-	netdev->phydev = NULL;
+	if (phy_is_pseudo_fixed_link(netdev->phydev))
+		lan743x_virtual_phy_disconnect(netdev->phydev);
+	else
+		phy_disconnect(netdev->phydev);
 }
 
 static int lan743x_phy_open(struct lan743x_adapter *adapter)
@@ -1019,11 +1026,22 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
 		/* try internal phy */
 		phydev = phy_find_first(adapter->mdiobus);
 		if (!phydev)
+			phydev = lan743x_virtual_phy(adapter, mii_regs,
+						     mii_regs_count);
+
+		if (!phydev || IS_ERR(phydev))
 			goto return_error;
 
-		ret = phy_connect_direct(netdev, phydev,
-					 lan743x_phy_link_status_change,
-					 PHY_INTERFACE_MODE_GMII);
+		if (phy_is_pseudo_fixed_link(phydev)) {
+			ret = phy_connect_direct(netdev, phydev,
+						 lan743x_virtual_phy_status_change,
+						 PHY_INTERFACE_MODE_MII);
+		} else {
+			ret = phy_connect_direct(netdev, phydev,
+						 lan743x_phy_link_status_change,
+						 PHY_INTERFACE_MODE_GMII);
+		}
+
 		if (ret)
 			goto return_error;
 	}
@@ -1031,6 +1049,15 @@ static int lan743x_phy_open(struct lan743x_adapter *adapter)
 	/* MAC doesn't support 1000T Half */
 	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
 
+	if (phy_is_pseudo_fixed_link(phydev)) {
+		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_TP_BIT);
+		linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+				 phydev->supported);
+		linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+				 phydev->supported);
+		phy_advertise_supported(phydev);
+	}
+
 	/* support both flow controls */
 	phy_support_asym_pause(phydev);
 	phy->fc_request_control = (FLOW_CTRL_RX | FLOW_CTRL_TX);
@@ -2580,11 +2607,20 @@ static netdev_tx_t lan743x_netdev_xmit_frame(struct sk_buff *skb,
 static int lan743x_netdev_ioctl(struct net_device *netdev,
 				struct ifreq *ifr, int cmd)
 {
+	int ret;
+
 	if (!netif_running(netdev))
 		return -EINVAL;
+
 	if (cmd == SIOCSHWTSTAMP)
 		return lan743x_ptp_ioctl(netdev, ifr, cmd);
-	return phy_mii_ioctl(netdev->phydev, ifr, cmd);
+
+	if (phy_is_pseudo_fixed_link(netdev->phydev))
+		ret = lan743x_virtual_phy_mii_ioctl(netdev->phydev, ifr, cmd);
+	else
+		ret = phy_mii_ioctl(netdev->phydev, ifr, cmd);
+
+	return ret;
 }
 
 static void lan743x_netdev_set_multicast(struct net_device *netdev)
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 404af3f4635e..8e16fd0f166a 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -109,6 +109,7 @@
 #define MAC_CR_EEE_EN_			BIT(17)
 #define MAC_CR_ADD_			BIT(12)
 #define MAC_CR_ASD_			BIT(11)
+#define MAC_CR_INT_LOOPBACK_		BIT(10)
 #define MAC_CR_CNTR_RST_		BIT(5)
 #define MAC_CR_DPX_			BIT(3)
 #define MAC_CR_CFG_H_			BIT(2)
diff --git a/drivers/net/ethernet/microchip/lan743x_virtual_phy.c b/drivers/net/ethernet/microchip/lan743x_virtual_phy.c
new file mode 100644
index 000000000000..b6bf7c016448
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan743x_virtual_phy.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (C) 2021 Sergej Bauer
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
+#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+#include "lan743x_main.h"
+#include "lan743x_ethtool.h"
+#include "lan743x_virtual_phy.h"
+
+static u16 regs802p3[32];
+
+int lan743x_virtual_phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr,
+				  int cmd)
+{
+	struct ethtool_link_ksettings ksettings;
+	struct net_device *netdev = phydev->attached_dev;
+	struct mii_ioctl_data *mii_data = if_mii(ifr);
+	int ret = 0;
+	u16 val = mii_data->val_in;
+	u16 reg_num = mii_data->reg_num;
+
+	if (reg_num > 0x1f)
+		return -ERANGE;
+
+	memset(&ksettings, 0, sizeof(ksettings));
+	phy_ethtool_get_link_ksettings(netdev, &ksettings);
+	ksettings.base.autoneg = AUTONEG_ENABLE;
+
+	switch (cmd) {
+	case SIOCGMIIPHY:
+		break;
+	case SIOCGMIIREG:
+		mii_data->val_out = regs802p3[reg_num];
+		break;
+	case SIOCSMIIREG:
+		switch (reg_num) {
+		case MII_BMCR:
+			val &= ~BMCR_RESET;
+			if (!(val & BMCR_FULLDPLX))
+				val |= BMCR_FULLDPLX;
+			val &= ~0x1f;
+
+			if (val & BMCR_ANRESTART)
+				val &= ~BMCR_ANRESTART;
+
+			if ((val & BMCR_SPEED1000) && (val & BMCR_SPEED100)) {
+				ret = -EINVAL;
+				netdev_err(netdev, "invalid bits 0.6 and 0.13");
+				break;
+			}
+
+			ksettings.base.duplex = DUPLEX_FULL;
+
+			if (val & BMCR_SPEED1000)
+				ksettings.base.speed = SPEED_1000;
+			else if (val & BMCR_SPEED100)
+				ksettings.base.speed = SPEED_100;
+			else
+				ksettings.base.speed = SPEED_10;
+
+			break;
+
+		case 1:
+		case 2:
+		case 3:
+		case 15:
+		default:
+			regs802p3[reg_num] = val;
+			break;
+		}
+		ret = lan743x_set_virtual_link_ksettings(netdev, &ksettings);
+		if (ret == 0)
+			regs802p3[reg_num] = val;
+
+		break;
+	default:
+		netdev_err(netdev, "not supported ioctl %X\n", cmd);
+		ret = -EOPNOTSUPP;
+	};
+
+	return ret;
+}
+
+void lan743x_virtual_phy_disconnect(struct phy_device *phydev)
+{
+	struct net_device *attached_dev = phydev->attached_dev;
+
+	if (phydev->sysfs_links) {
+		if (phydev->attached_dev)
+			sysfs_remove_link(&attached_dev->dev.kobj,
+					  "phydev");
+		sysfs_remove_link(&phydev->mdio.dev.kobj,
+				  "attached_dev");
+	}
+
+	fixed_phy_unregister(phydev);
+}
+
+void lan743x_virtual_phy_status_change(struct net_device *netdev)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+	struct phy_device *phydev = netdev->phydev;
+	u32 data;
+
+	if (!netdev->phydev)
+		return;
+
+	if (phydev->state == PHY_RUNNING) {
+		data = lan743x_csr_read(adapter, MAC_CR);
+		data |= MAC_CR_INT_LOOPBACK_;
+		data &= ~MAC_CR_MII_EN_;
+		data |= MAC_CR_DPX_;
+
+		switch (phydev->speed) {
+		case SPEED_10:
+			data &= ~MAC_CR_CFG_H_;
+			data &= ~MAC_CR_CFG_L_;
+		break;
+		case SPEED_100:
+			data &= ~MAC_CR_CFG_H_;
+			data |= MAC_CR_CFG_L_;
+		break;
+		case SPEED_1000:
+			data |= MAC_CR_CFG_H_;
+			data &= ~MAC_CR_CFG_L_;
+		break;
+		}
+		lan743x_csr_write(adapter, MAC_CR, data);
+	}
+	phy_print_status(phydev);
+}
+
+struct phy_device *lan743x_virtual_phy(struct lan743x_adapter *adapter,
+				       char *mii_regs[], int mii_regs_count)
+{
+	struct phy_device *phydev = NULL;
+	struct net_device *netdev = adapter->netdev;
+	struct mii_ioctl_data mii_data;
+	struct ifreq ifr;
+	long res;
+	int ret, i;
+
+	struct fixed_phy_status status = {
+		.link = 1,
+		.speed = SPEED_1000,
+		.duplex = DUPLEX_FULL,
+		.asym_pause = 1,
+	};
+
+	phydev = fixed_phy_register(PHY_POLL, &status, NULL);
+	if (!phydev || IS_ERR(phydev)) {
+		netif_err(adapter, ifup, adapter->netdev,
+			  "failed to regiter fixed_phy\n");
+		goto out;
+	}
+	phydev->attached_dev = netdev;
+	netdev->phydev = phydev;
+
+	linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+			   phydev->supported);
+	linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+			   phydev->supported);
+	linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+			   phydev->supported);
+
+	if (mii_regs_count > 0) {
+		for (i = 0; i < mii_regs_count; i++) {
+			mii_data.reg_num = i;
+			ret = kstrtol(mii_regs[i], 16, &res);
+
+			if (ret == 0)
+				mii_data.val_in = res;
+			else
+				mii_data.val_in = 0xffff;
+
+			memcpy(&ifr.ifr_ifru.ifru_data, &mii_data,
+			       sizeof(mii_data));
+			ret = lan743x_virtual_phy_mii_ioctl(phydev, &ifr,
+							    SIOCSMIIREG);
+			if (ret < 0)
+				return NULL;
+		}
+	} else {
+		mii_data.reg_num = MII_BMSR;
+		mii_data.val_in = BMSR_100FULL | BMSR_10FULL | BMSR_ESTATEN |
+			BMSR_ANEGCOMPLETE | BMSR_ANEGCAPABLE | BMSR_LSTATUS |
+			BMSR_ERCAP;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+
+		mii_data.reg_num = MII_PHYSID1;
+		mii_data.val_in = (adapter->csr.id_rev & ID_REV_ID_MASK_) >> 16;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+
+		mii_data.reg_num = MII_PHYSID2;
+		mii_data.val_in = adapter->csr.id_rev & ID_REV_CHIP_REV_MASK_;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+
+		mii_data.reg_num = MII_ADVERTISE;
+		mii_data.val_in = ADVERTISE_100FULL | ADVERTISE_10FULL |
+			ADVERTISE_LPACK;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+
+		mii_data.reg_num = MII_LPA;
+		mii_data.val_in = ADVERTISE_100FULL | ADVERTISE_10FULL |
+			ADVERTISE_LPACK;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+
+		mii_data.reg_num = MII_EXPANSION;
+		mii_data.val_in = EXPANSION_NWAY | EXPANSION_ENABLENPAGE |
+			EXPANSION_NPCAPABLE;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+
+		mii_data.reg_num = MII_CTRL1000;
+		mii_data.val_in = ADVERTISE_1000FULL;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+
+		mii_data.reg_num = MII_STAT1000;
+		mii_data.val_in = LPA_1000FULL | LPA_1000REMRXOK |
+			LPA_1000LOCALRXOK | LPA_1000MSRES;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+
+		mii_data.reg_num = MII_ESTATUS;
+		mii_data.val_in = ESTATUS_1000_TFULL;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+
+		mii_data.reg_num = MII_BMCR;
+		mii_data.val_in = BMCR_SPEED1000 | BMCR_FULLDPLX |
+			BMCR_LOOPBACK | BMCR_ANENABLE;
+		memcpy(&ifr.ifr_ifru.ifru_data, &mii_data, sizeof(mii_data));
+		lan743x_virtual_phy_mii_ioctl(phydev, &ifr, SIOCSMIIREG);
+	}
+
+	phydev->attached_dev = NULL;
+out:
+	return phydev;
+}
+
+int lan743x_set_virtual_link_ksettings(struct net_device *netdev,
+				       const struct ethtool_link_ksettings *cmd)
+{
+	struct ethtool_link_ksettings *cmd_ref =
+		(struct ethtool_link_ksettings *)cmd;
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+	u32 speed = cmd->base.speed;
+	u8 duplex = cmd->base.duplex;
+	u16 v = 0;
+	u32 data;
+
+	if (!netdev->phydev)
+		return -ENETDOWN;
+	if (speed &&
+	    speed != SPEED_10 && speed != SPEED_100 && speed != SPEED_1000) {
+		netdev_err(netdev, "%s: unknown speed %d\n", netdev->name,
+			   speed);
+		return -EINVAL;
+	}
+
+	v = regs802p3[0];
+	v &= ~(BMCR_SPEED1000 | BMCR_SPEED100);
+	data = lan743x_csr_read(adapter, MAC_CR);
+	duplex = DUPLEX_FULL;
+
+	if (speed != adapter->netdev->phydev->speed) {
+		lan743x_mac_close(adapter);
+		switch (speed) {
+		case 0:
+			break;
+		case SPEED_10:
+			data &= ~(MAC_CR_CFG_H_ | MAC_CR_CFG_L_);
+			lan743x_csr_write(adapter, MAC_CR, data);
+
+			regs802p3[MII_ADVERTISE] = ADVERTISE_10FULL |
+				ADVERTISE_100FULL |
+				ADVERTISE_LPACK;
+			regs802p3[MII_LPA] = LPA_10FULL | LPA_LPACK;
+			regs802p3[MII_EXPANSION] = ESTATUS_1000_TFULL;
+			regs802p3[MII_CTRL1000] = ADVERTISE_1000FULL;
+			regs802p3[MII_STAT1000] = 0;
+			break;
+		case SPEED_100:
+			v |= BMCR_SPEED100;
+			data &= ~MAC_CR_CFG_H_;
+			data |= MAC_CR_CFG_L_;
+			lan743x_csr_write(adapter, MAC_CR, data);
+
+			regs802p3[MII_ADVERTISE] = ADVERTISE_10FULL |
+				ADVERTISE_100FULL |
+				ADVERTISE_LPACK;
+			regs802p3[MII_LPA] = LPA_10FULL | LPA_100FULL |
+				LPA_LPACK;
+			regs802p3[MII_EXPANSION] = ESTATUS_1000_TFULL;
+			regs802p3[MII_CTRL1000] = ADVERTISE_1000FULL;
+			regs802p3[MII_STAT1000] = 0;
+			break;
+		case SPEED_1000:
+			v |= BMCR_SPEED1000;
+			data |= MAC_CR_CFG_H_;
+			data &= ~MAC_CR_CFG_L_;
+			lan743x_csr_write(adapter, MAC_CR, data);
+
+			regs802p3[MII_ADVERTISE] = ADVERTISE_10FULL |
+				ADVERTISE_100FULL |
+				ADVERTISE_LPACK;
+			regs802p3[MII_LPA] = LPA_10FULL | LPA_100FULL |
+				LPA_LPACK;
+			regs802p3[MII_EXPANSION] = ESTATUS_1000_TFULL;
+			regs802p3[MII_CTRL1000] = ADVERTISE_1000FULL;
+			regs802p3[MII_STAT1000] = LPA_1000FULL |
+				LPA_1000REMRXOK | LPA_1000LOCALRXOK |
+				LPA_1000MSRES;
+			break;
+		};
+		lan743x_mac_open(adapter);
+
+		v |= BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_ANENABLE;
+		regs802p3[0] = v;
+	}
+
+	cmd_ref->base.duplex = duplex;
+	cmd_ref->base.autoneg = AUTONEG_ENABLE;
+
+	return phy_ethtool_set_link_ksettings(netdev, cmd_ref);
+}
+
diff --git a/drivers/net/ethernet/microchip/lan743x_virtual_phy.h b/drivers/net/ethernet/microchip/lan743x_virtual_phy.h
new file mode 100644
index 000000000000..caef07d73d74
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan743x_virtual_phy.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2021 Sergej Bauer */
+#ifndef LAN743X_FAKE_PHY_H
+#define LAN743X_FAKE_PHY_H
+
+#include "lan743x_main.h"
+
+struct phy_device *lan743x_virtual_phy(struct lan743x_adapter *adapter,
+				       char *mii_regs[], int mii_regs_count);
+void lan743x_virtual_phy_disconnect(struct phy_device *phydev);
+int lan743x_virtual_phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr,
+				  int cmd);
+void lan743x_virtual_phy_status_change(struct net_device *netdev);
+int lan743x_set_virtual_link_ksettings(struct net_device *netdev,
+				       const struct ethtool_link_ksettings *cmd);
+
+int lan743x_mac_open(struct lan743x_adapter *adapter);
+void lan743x_mac_close(struct lan743x_adapter *adapter);
+
+#endif

             reply	other threads:[~2021-01-22 21:55 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-22 21:42 Sergej Bauer [this message]
2021-01-22 21:52 ` [PATCH v2] lan743x: add virtual PHY for PHY-less devices Florian Fainelli
2021-01-22 22:11   ` Sergej Bauer
2021-01-22 22:08 ` Andrew Lunn
2021-01-22 23:09   ` Sergej Bauer
2021-01-22 23:23     ` Andrew Lunn
2021-01-22 23:58       ` Sergej Bauer
2021-01-23  0:01         ` Florian Fainelli
2021-01-23  1:01           ` Sergej Bauer
2021-01-23  1:32             ` Andrew Lunn
2021-01-23  4:01               ` Sergej Bauer
2021-01-25  8:57               ` Sergej Bauer
2021-01-23  1:39             ` Florian Fainelli
2021-01-25  8:57               ` Sergej Bauer
2021-01-25 10:23       ` Sergej Bauer

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=20210122214247.6536-1-sbauer@blackbox.su \
    --to=sbauer@blackbox.su \
    --cc=UNGLinuxDriver@microchip.com \
    --cc=andrew@lunn.ch \
    --cc=arnd@arndb.de \
    --cc=bryan.whitehead@microchip.com \
    --cc=davem@davemloft.net \
    --cc=f.fainelli@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=madalin.bucur@oss.nxp.com \
    --cc=mark.einon@gmail.com \
    --cc=masahiroy@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=simon.horman@netronome.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).