* [PATCH net-next v3 1/5] net: lan743x: rename is_sgmii_en to is_pcs_en
2026-05-08 5:21 [PATCH net-next v3 0/5] net: lan743x: Add SFP support for PCI11x1x Thangaraj Samynathan
@ 2026-05-08 5:21 ` Thangaraj Samynathan
2026-05-08 5:21 ` [PATCH net-next v3 2/5] net: lan743x: read SFP straps from PCI11x1x device Thangaraj Samynathan
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Thangaraj Samynathan @ 2026-05-08 5:21 UTC (permalink / raw)
To: netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, bryan.whitehead,
UNGLinuxDriver, linux, linux-kernel
The flag is_sgmii_en indicates whether the PCS interface is enabled.
However, the name implies that the interface is strictly SGMII, which is
misleading.
Rename the variable to is_pcs_en to better reflect that the flag
represents the PCS enable state rather than a specific interface mode.
Update all references and logs accordingly (but keep device registers
unchanged to match its documentation).
No functional change intended.
Signed-off-by: Thangaraj Samynathan <thangaraj.s@microchip.com>
---
.../net/ethernet/microchip/lan743x_ethtool.c | 4 ++--
drivers/net/ethernet/microchip/lan743x_main.c | 18 +++++++++---------
drivers/net/ethernet/microchip/lan743x_main.h | 2 +-
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
index 9195419ecee0..743acfd56554 100644
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -1312,7 +1312,7 @@ static int lan743x_get_regs_len(struct net_device *dev)
struct lan743x_adapter *adapter = netdev_priv(dev);
u32 num_regs = MAX_LAN743X_ETH_COMMON_REGS;
- if (adapter->is_sgmii_en)
+ if (adapter->is_pcs_en)
num_regs += MAX_LAN743X_ETH_SGMII_REGS;
return num_regs * sizeof(u32);
@@ -1333,7 +1333,7 @@ static void lan743x_get_regs(struct net_device *dev,
lan743x_common_regs(dev, p);
p = (u32 *)p + MAX_LAN743X_ETH_COMMON_REGS;
- if (adapter->is_sgmii_en) {
+ if (adapter->is_pcs_en) {
lan743x_sgmii_regs(dev, p);
p = (u32 *)p + MAX_LAN743X_ETH_SGMII_REGS;
}
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index f3332417162e..fad4a246e06e 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -59,22 +59,22 @@ static void pci11x1x_strap_get_status(struct lan743x_adapter *adapter)
hw_cfg & HW_CFG_RST_PROTECT_)) ||
(strap & STRAP_READ_USE_SGMII_EN_)) {
if (strap & STRAP_READ_SGMII_EN_)
- adapter->is_sgmii_en = true;
+ adapter->is_pcs_en = true;
else
- adapter->is_sgmii_en = false;
+ adapter->is_pcs_en = false;
} else {
fpga_rev = lan743x_csr_read(adapter, FPGA_REV);
if (fpga_rev) {
if (fpga_rev & FPGA_SGMII_OP)
- adapter->is_sgmii_en = true;
+ adapter->is_pcs_en = true;
else
- adapter->is_sgmii_en = false;
+ adapter->is_pcs_en = false;
} else {
- adapter->is_sgmii_en = false;
+ adapter->is_pcs_en = false;
}
}
netif_dbg(adapter, drv, adapter->netdev,
- "SGMII I/F %sable\n", adapter->is_sgmii_en ? "En" : "Dis");
+ "PCS I/F %s\n", str_enable_disable(adapter->is_pcs_en));
}
static bool is_pci11x1x_chip(struct lan743x_adapter *adapter)
@@ -1361,7 +1361,7 @@ static void lan743x_phy_interface_select(struct lan743x_adapter *adapter)
data = lan743x_csr_read(adapter, MAC_CR);
id_rev = adapter->csr.id_rev & ID_REV_ID_MASK_;
- if (adapter->is_pci11x1x && adapter->is_sgmii_en)
+ if (adapter->is_pci11x1x && adapter->is_pcs_en)
adapter->phy_interface = PHY_INTERFACE_MODE_SGMII;
else if (id_rev == ID_REV_ID_LAN7430_)
adapter->phy_interface = PHY_INTERFACE_MODE_GMII;
@@ -3515,7 +3515,7 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
mutex_init(&adapter->sgmii_rw_lock);
pci11x1x_set_rfe_rd_fifo_threshold(adapter);
sgmii_ctl = lan743x_csr_read(adapter, SGMII_CTL);
- if (adapter->is_sgmii_en) {
+ if (adapter->is_pcs_en) {
sgmii_ctl |= SGMII_CTL_SGMII_ENABLE_;
sgmii_ctl &= ~SGMII_CTL_SGMII_POWER_DN_;
} else {
@@ -3580,7 +3580,7 @@ static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
adapter->mdiobus->priv = (void *)adapter;
if (adapter->is_pci11x1x) {
- if (adapter->is_sgmii_en) {
+ if (adapter->is_pcs_en) {
netif_dbg(adapter, drv, adapter->netdev,
"SGMII operation\n");
adapter->mdiobus->read = lan743x_mdiobus_read_c22;
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 160d94a7cee6..f0fa0580b04e 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -1070,7 +1070,7 @@ struct lan743x_adapter {
struct lan743x_tx tx[PCI11X1X_USED_TX_CHANNELS];
struct lan743x_rx rx[LAN743X_USED_RX_CHANNELS];
bool is_pci11x1x;
- bool is_sgmii_en;
+ bool is_pcs_en;
/* protect ethernet syslock */
spinlock_t eth_syslock_spinlock;
bool eth_syslock_en;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH net-next v3 2/5] net: lan743x: read SFP straps from PCI11x1x device
2026-05-08 5:21 [PATCH net-next v3 0/5] net: lan743x: Add SFP support for PCI11x1x Thangaraj Samynathan
2026-05-08 5:21 ` [PATCH net-next v3 1/5] net: lan743x: rename is_sgmii_en to is_pcs_en Thangaraj Samynathan
@ 2026-05-08 5:21 ` Thangaraj Samynathan
2026-05-08 5:21 ` [PATCH net-next v3 3/5] net: lan743x: Add support to software-nodes for SFP Thangaraj Samynathan
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Thangaraj Samynathan @ 2026-05-08 5:21 UTC (permalink / raw)
To: netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, bryan.whitehead,
UNGLinuxDriver, linux, linux-kernel
Reads the SFP enable bits from the strap registers to determine
if the hardware is configured for SFP usage.
- Add STRAP_SFP_USE_EN_ and STRAP_SFP_EN_ definitions to read SFP
straps.
- Store SFP status in the adapter's is_sfp_support_en flag.
- Add a validation check to ensure PCS is enabled when SFP support
is requested, as SFP operation requires the PCS interface.
- Refactor debug logging to use the str_enable_disable() helper for
consistency with modern kernel standards.
Signed-off-by: Thangaraj Samynathan <thangaraj.s@microchip.com>
---
drivers/net/ethernet/microchip/lan743x_main.c | 16 ++++++++++++++++
drivers/net/ethernet/microchip/lan743x_main.h | 3 +++
2 files changed, 19 insertions(+)
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index fad4a246e06e..867310dbe9ba 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -62,6 +62,12 @@ static void pci11x1x_strap_get_status(struct lan743x_adapter *adapter)
adapter->is_pcs_en = true;
else
adapter->is_pcs_en = false;
+
+ if ((strap & STRAP_SFP_USE_EN_) && (strap & STRAP_SFP_EN_))
+ adapter->is_sfp_support_en = true;
+ else
+ adapter->is_sfp_support_en = false;
+
} else {
fpga_rev = lan743x_csr_read(adapter, FPGA_REV);
if (fpga_rev) {
@@ -73,8 +79,17 @@ static void pci11x1x_strap_get_status(struct lan743x_adapter *adapter)
adapter->is_pcs_en = false;
}
}
+
+ if (adapter->is_pci11x1x && !adapter->is_pcs_en &&
+ adapter->is_sfp_support_en) {
+ netif_err(adapter, drv, adapter->netdev,
+ "Invalid EEPROM configuration: SFP_EN strap specified without SGMII_EN strap\n");
+ }
+
netif_dbg(adapter, drv, adapter->netdev,
"PCS I/F %s\n", str_enable_disable(adapter->is_pcs_en));
+ netif_dbg(adapter, drv, adapter->netdev,
+ "SFP support %s\n", str_enable_disable(adapter->is_sfp_support_en));
}
static bool is_pci11x1x_chip(struct lan743x_adapter *adapter)
@@ -3665,6 +3680,7 @@ static int lan743x_pcidev_probe(struct pci_dev *pdev,
NETIF_MSG_LINK | NETIF_MSG_IFUP |
NETIF_MSG_IFDOWN | NETIF_MSG_TX_QUEUED;
netdev->max_mtu = LAN743X_MAX_FRAME_SIZE;
+ adapter->is_sfp_support_en = false;
of_get_mac_address(pdev->dev.of_node, adapter->mac_address);
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index f0fa0580b04e..26c30dc2e55c 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -37,6 +37,8 @@
#define STRAP_READ (0x0C)
#define STRAP_READ_USE_SGMII_EN_ BIT(22)
+#define STRAP_SFP_USE_EN_ BIT(31)
+#define STRAP_SFP_EN_ BIT(15)
#define STRAP_READ_SGMII_EN_ BIT(6)
#define STRAP_READ_SGMII_REFCLK_ BIT(5)
#define STRAP_READ_SGMII_2_5G_ BIT(4)
@@ -1081,6 +1083,7 @@ struct lan743x_adapter {
u8 max_tx_channels;
u8 used_tx_channels;
u8 max_vector_count;
+ bool is_sfp_support_en;
#define LAN743X_ADAPTER_FLAG_OTP BIT(0)
u32 flags;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH net-next v3 3/5] net: lan743x: Add support to software-nodes for SFP
2026-05-08 5:21 [PATCH net-next v3 0/5] net: lan743x: Add SFP support for PCI11x1x Thangaraj Samynathan
2026-05-08 5:21 ` [PATCH net-next v3 1/5] net: lan743x: rename is_sgmii_en to is_pcs_en Thangaraj Samynathan
2026-05-08 5:21 ` [PATCH net-next v3 2/5] net: lan743x: read SFP straps from PCI11x1x device Thangaraj Samynathan
@ 2026-05-08 5:21 ` Thangaraj Samynathan
2026-05-08 5:21 ` [PATCH net-next v3 4/5] net: lan743x: Register SFP platform device for PCI11x1x Thangaraj Samynathan
2026-05-08 5:21 ` [PATCH net-next v3 5/5] net: lan743x: Add PCS/XPCS support for SFP on PCI11x1x Thangaraj Samynathan
4 siblings, 0 replies; 6+ messages in thread
From: Thangaraj Samynathan @ 2026-05-08 5:21 UTC (permalink / raw)
To: netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, bryan.whitehead,
UNGLinuxDriver, linux, linux-kernel
Register software nodes and define the required device properties.
The software node hierarchy describes the hardware connections for
SFP support, including:
- GPIO pins used for SFP control and status signals (TX fault,
TX disable, LOS, mod-def0, rate-select0)
- the I2C bus used for SFP module EEPROM access
- the SFP cage signal connections
- the phylink configuration in in-band status mode
Signed-off-by: Thangaraj Samynathan <thangaraj.s@microchip.com>
---
drivers/net/ethernet/microchip/Kconfig | 2 +
drivers/net/ethernet/microchip/lan743x_main.c | 196 +++++++++++++++++-
drivers/net/ethernet/microchip/lan743x_main.h | 81 ++++++++
3 files changed, 277 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
index ee046468652c..a83db3c7404f 100644
--- a/drivers/net/ethernet/microchip/Kconfig
+++ b/drivers/net/ethernet/microchip/Kconfig
@@ -50,6 +50,8 @@ config LAN743X
select CRC16
select CRC32
select PHYLINK
+ select I2C_PCI1XXXX
+ select GP_PCI1XXXX
help
Support for the Microchip LAN743x and PCI11x1x families of PCI
Express Ethernet devices
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 867310dbe9ba..b90b35cef2e6 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -16,6 +16,7 @@
#include <linux/iopoll.h>
#include <linux/crc16.h>
#include <linux/phylink.h>
+
#include "lan743x_main.h"
#include "lan743x_ethtool.h"
@@ -112,6 +113,91 @@ static void lan743x_pci_cleanup(struct lan743x_adapter *adapter)
pci_disable_device(adapter->pdev);
}
+static void *pci1xxxx_perif_drvdata_get(struct lan743x_adapter *adapter,
+ u16 perif_id)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct pci_bus *perif_bus;
+ struct pci_dev *perif_dev;
+ struct pci_dev *br_dev;
+ struct pci_bus *br_bus;
+ struct pci_dev *dev;
+
+ /* PCI11x1x devices' PCIe topology consists of a top level pcie
+ * switch with up to four downstream ports, some of which have
+ * integrated endpoints connected to them. One of the downstream ports
+ * has an embedded single function pcie ethernet controller which is
+ * handled by this driver. Another downstream port has an
+ * embedded multifunction pcie endpoint, with four pcie functions
+ * (the "peripheral controllers": I2C controller, GPIO controller,
+ * UART controllers, SPI controllers)
+ * The code below navigates the PCI11x1x topology
+ * to find (by matching its PCI device ID) the peripheral controller
+ * that should be paired to the embedded ethernet controller.
+ */
+
+ br_dev = pci_upstream_bridge(pdev);
+ if (!br_dev) {
+ netif_err(adapter, drv, adapter->netdev,
+ "upstream bridge not found\n");
+ return br_dev;
+ }
+
+ br_bus = br_dev->bus;
+ list_for_each_entry(dev, &br_bus->devices, bus_list) {
+ if (dev->vendor == PCI1XXXX_VENDOR_ID &&
+ (dev->device & ~PCI1XXXX_DEV_MASK) == PCI1XXXX_BR_PERIF_ID) {
+ perif_bus = dev->subordinate;
+ list_for_each_entry(perif_dev, &perif_bus->devices,
+ bus_list) {
+ if (perif_dev->vendor == PCI1XXXX_VENDOR_ID &&
+ (perif_dev->device & ~PCI1XXXX_DEV_MASK) ==
+ perif_id)
+ return pci_get_drvdata(perif_dev);
+ }
+ }
+ }
+
+ netif_err(adapter, drv, adapter->netdev,
+ "pci1xxxx peripheral (0x%X) device not found\n", perif_id);
+
+ return NULL;
+}
+
+static int pci1xxxx_i2c_adapter_get(struct lan743x_adapter *adapter)
+{
+ struct pci1xxxx_i2c *i2c_drvdata;
+
+ i2c_drvdata = pci1xxxx_perif_drvdata_get(adapter, PCI1XXXX_PERIF_I2C_ID);
+ if (!i2c_drvdata)
+ return -EPROBE_DEFER;
+
+ adapter->i2c_adap = &i2c_drvdata->adap;
+ strscpy(adapter->nodes->i2c_name, adapter->i2c_adap->name,
+ sizeof(adapter->nodes->i2c_name));
+ netif_dbg(adapter, drv, adapter->netdev, "Found %s\n",
+ adapter->i2c_adap->name);
+
+ return 0;
+}
+
+static int pci1xxxx_gpio_dev_get(struct lan743x_adapter *adapter)
+{
+ struct aux_bus_device *aux_bus;
+ struct device *gpio_dev;
+
+ aux_bus = pci1xxxx_perif_drvdata_get(adapter, PCI1XXXX_PERIF_GPIO_ID);
+ if (!aux_bus)
+ return -EPROBE_DEFER;
+
+ gpio_dev = &aux_bus->aux_device_wrapper[1]->aux_dev.dev;
+ strscpy(adapter->nodes->gpio_name, dev_name(gpio_dev),
+ sizeof(adapter->nodes->gpio_name));
+ netif_dbg(adapter, drv, adapter->netdev, "Found %s\n",
+ adapter->nodes->gpio_name);
+ return 0;
+}
+
static int lan743x_pci_init(struct lan743x_adapter *adapter,
struct pci_dev *pdev)
{
@@ -2890,6 +2976,96 @@ static int lan743x_rx_open(struct lan743x_rx *rx)
return ret;
}
+static void lan743x_swnodes_unregister(struct lan743x_adapter *adapter)
+{
+ if (adapter->nodes) {
+ software_node_unregister_node_group(adapter->nodes->group);
+ kfree(adapter->nodes);
+ adapter->nodes = NULL;
+ }
+}
+
+static int lan743x_swnodes_register(struct lan743x_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct lan743x_sw_nodes *nodes;
+ struct software_node *swnodes;
+ int ret;
+ u32 id;
+
+ nodes = kzalloc_obj(*nodes);
+ if (!nodes)
+ return -ENOMEM;
+
+ adapter->nodes = nodes;
+
+ ret = pci1xxxx_gpio_dev_get(adapter);
+ if (ret < 0)
+ return ret;
+
+ ret = pci1xxxx_i2c_adapter_get(adapter);
+ if (ret < 0)
+ return ret;
+
+ id = (pdev->bus->number << 8) | pdev->devfn;
+ snprintf(nodes->sfp_name, sizeof(nodes->sfp_name), "sfp-%d", id);
+ snprintf(nodes->phylink_name, sizeof(nodes->phylink_name),
+ "mchp-pci1xxxx-phylink-%d", id);
+
+ swnodes = nodes->swnodes;
+
+ nodes->gpio_props[0] = PROPERTY_ENTRY_STRING("pinctrl-names", "default");
+ swnodes[SWNODE_GPIO] = NODE_PROP(nodes->gpio_name, nodes->gpio_props);
+
+ nodes->tx_fault_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO],
+ PCI11X1X_TX_FAULT_GPIO,
+ GPIO_ACTIVE_HIGH);
+ nodes->tx_disable_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO],
+ PCI11X1X_TX_DIS_GPIO,
+ GPIO_ACTIVE_HIGH);
+ nodes->mod_def0_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO],
+ PCI11X1X_MOD_DEF0_GPIO,
+ GPIO_ACTIVE_LOW);
+ nodes->los_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO],
+ PCI11X1X_LOS_GPIO,
+ GPIO_ACTIVE_HIGH);
+ nodes->rate_sel0_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO],
+ PCI11X1X_RATE_SEL0_GPIO,
+ GPIO_ACTIVE_HIGH);
+
+ nodes->i2c_props[0] = PROPERTY_ENTRY_STRING("pinctrl-names", "default");
+ swnodes[SWNODE_I2C] = NODE_PROP(nodes->i2c_name, nodes->i2c_props);
+ nodes->i2c_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_I2C]);
+
+ nodes->sfp_props[0] = PROPERTY_ENTRY_STRING("compatible", "sff,sfp");
+ nodes->sfp_props[1] = PROPERTY_ENTRY_REF_ARRAY("i2c-bus", nodes->i2c_ref);
+ nodes->sfp_props[2] = PROPERTY_ENTRY_REF_ARRAY("tx-fault-gpios",
+ nodes->tx_fault_ref);
+ nodes->sfp_props[3] = PROPERTY_ENTRY_REF_ARRAY("tx-disable-gpios",
+ nodes->tx_disable_ref);
+ nodes->sfp_props[4] = PROPERTY_ENTRY_REF_ARRAY("mod-def0-gpios",
+ nodes->mod_def0_ref);
+ nodes->sfp_props[5] = PROPERTY_ENTRY_REF_ARRAY("los-gpios",
+ nodes->los_ref);
+ nodes->sfp_props[6] = PROPERTY_ENTRY_REF_ARRAY("rate-select0-gpios",
+ nodes->rate_sel0_ref);
+ swnodes[SWNODE_SFP] = NODE_PROP(nodes->sfp_name, nodes->sfp_props);
+ nodes->sfp_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_SFP]);
+ nodes->phylink_props[0] = PROPERTY_ENTRY_STRING("managed",
+ "in-band-status");
+ nodes->phylink_props[1] = PROPERTY_ENTRY_REF_ARRAY("sfp",
+ nodes->sfp_ref);
+ swnodes[SWNODE_PHYLINK] = NODE_PROP(nodes->phylink_name,
+ nodes->phylink_props);
+
+ nodes->group[SWNODE_GPIO] = &swnodes[SWNODE_GPIO];
+ nodes->group[SWNODE_I2C] = &swnodes[SWNODE_I2C];
+ nodes->group[SWNODE_SFP] = &swnodes[SWNODE_SFP];
+ nodes->group[SWNODE_PHYLINK] = &swnodes[SWNODE_PHYLINK];
+
+ return software_node_register_node_group(nodes->group);
+}
+
static int lan743x_phylink_sgmii_config(struct lan743x_adapter *adapter)
{
u32 sgmii_ctl;
@@ -3134,7 +3310,9 @@ static const struct phylink_mac_ops lan743x_phylink_mac_ops = {
static int lan743x_phylink_create(struct lan743x_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ struct fwnode_handle *fwnode = NULL;
struct phylink *pl;
+ int ret;
adapter->phylink_config.dev = &netdev->dev;
adapter->phylink_config.type = PHYLINK_NETDEV;
@@ -3174,11 +3352,24 @@ static int lan743x_phylink_create(struct lan743x_adapter *adapter)
adapter->phylink_config.supported_interfaces,
sizeof(adapter->phylink_config.lpi_interfaces));
- pl = phylink_create(&adapter->phylink_config, NULL,
- adapter->phy_interface, &lan743x_phylink_mac_ops);
+ if (adapter->is_sfp_support_en) {
+ ret = lan743x_swnodes_register(adapter);
+ if (ret) {
+ netdev_err(netdev, "failed to register software nodes\n");
+ return ret;
+ }
+ fwnode = software_node_fwnode(adapter->nodes->group[SWNODE_PHYLINK]);
+ if (!fwnode) {
+ lan743x_swnodes_unregister(adapter);
+ return -ENODEV;
+ }
+ }
+ pl = phylink_create(&adapter->phylink_config, fwnode,
+ adapter->phy_interface, &lan743x_phylink_mac_ops);
if (IS_ERR(pl)) {
netdev_err(netdev, "Could not create phylink (%pe)\n", pl);
+ lan743x_swnodes_unregister(adapter);
return PTR_ERR(pl);
}
@@ -3485,6 +3676,7 @@ static void lan743x_destroy_phylink(struct lan743x_adapter *adapter)
{
phylink_destroy(adapter->phylink);
adapter->phylink = NULL;
+ lan743x_swnodes_unregister(adapter);
}
static void lan743x_full_cleanup(struct lan743x_adapter *adapter)
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 26c30dc2e55c..48db45d41502 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -4,14 +4,59 @@
#ifndef _LAN743X_H
#define _LAN743X_H
+#include <linux/auxiliary_bus.h>
+#include <linux/gpio/machine.h>
+#include <linux/i2c.h>
#include <linux/phy.h>
#include <linux/phylink.h>
+#include <linux/property.h>
#include "lan743x_ptp.h"
#define DRIVER_AUTHOR "Bryan Whitehead <Bryan.Whitehead@microchip.com>"
#define DRIVER_DESC "LAN743x PCIe Gigabit Ethernet Driver"
#define DRIVER_NAME "lan743x"
+#define PCI1XXXX_VENDOR_ID 0x1055
+#define PCI1XXXX_BR_PERIF_ID 0xA00C
+#define PCI1XXXX_PERIF_I2C_ID 0xA003
+#define PCI1XXXX_PERIF_GPIO_ID 0xA005
+#define PCI1XXXX_DEV_MASK GENMASK(7, 4)
+#define PCI11X1X_TX_FAULT_GPIO 46
+#define PCI11X1X_TX_DIS_GPIO 47
+#define PCI11X1X_RATE_SEL0_GPIO 48
+#define PCI11X1X_LOS_GPIO 49
+#define PCI11X1X_MOD_DEF0_GPIO 51
+
+#define NODE_PROP(_NAME, _PROP) \
+ ((const struct software_node) { \
+ .name = _NAME, \
+ .properties = _PROP, \
+ })
+
+struct pci1xxxx_i2c {
+ struct completion i2c_xfer_done;
+ bool i2c_xfer_in_progress;
+ struct i2c_adapter adap;
+ void __iomem *i2c_base;
+ u32 freq;
+ u32 flags;
+};
+
+struct gp_aux_data_type {
+ int irq_num;
+ resource_size_t region_start;
+ resource_size_t region_length;
+};
+
+struct auxiliary_device_wrapper {
+ struct auxiliary_device aux_dev;
+ struct gp_aux_data_type gp_aux_data;
+};
+
+struct aux_bus_device {
+ struct auxiliary_device_wrapper *aux_device_wrapper[2];
+};
+
/* Register Definitions */
#define ID_REV (0x00)
#define ID_REV_ID_MASK_ (0xFFFF0000)
@@ -1049,6 +1094,40 @@ enum lan743x_sgmii_lsd {
#define MAC_SUPPORTED_WAKES (WAKE_BCAST | WAKE_UCAST | WAKE_MCAST | \
WAKE_MAGIC | WAKE_ARP)
+
+enum lan743x_swnodes {
+ SWNODE_GPIO = 0,
+ SWNODE_I2C,
+ SWNODE_SFP,
+ SWNODE_PHYLINK,
+ SWNODE_MAX
+};
+
+#define I2C_DRV_NAME 48
+#define GPIO_DRV_NAME 32
+#define SFP_NODE_NAME 32
+#define PHYLINK_NODE_NAME 32
+
+struct lan743x_sw_nodes {
+ char gpio_name[GPIO_DRV_NAME];
+ char i2c_name[I2C_DRV_NAME];
+ char sfp_name[SFP_NODE_NAME];
+ char phylink_name[PHYLINK_NODE_NAME];
+ struct property_entry gpio_props[1];
+ struct property_entry i2c_props[1];
+ struct property_entry sfp_props[8];
+ struct property_entry phylink_props[2];
+ struct software_node_ref_args i2c_ref[1];
+ struct software_node_ref_args tx_fault_ref[1];
+ struct software_node_ref_args tx_disable_ref[1];
+ struct software_node_ref_args mod_def0_ref[1];
+ struct software_node_ref_args los_ref[1];
+ struct software_node_ref_args rate_sel0_ref[1];
+ struct software_node_ref_args sfp_ref[1];
+ struct software_node swnodes[SWNODE_MAX];
+ const struct software_node *group[SWNODE_MAX + 1];
+};
+
struct lan743x_adapter {
struct net_device *netdev;
struct mii_bus *mdiobus;
@@ -1092,6 +1171,8 @@ struct lan743x_adapter {
struct phylink *phylink;
struct phylink_config phylink_config;
int rx_tstamp_filter;
+ struct lan743x_sw_nodes *nodes;
+ struct i2c_adapter *i2c_adap;
};
#define LAN743X_COMPONENT_FLAG_RX(channel) BIT(20 + (channel))
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH net-next v3 4/5] net: lan743x: Register SFP platform device for PCI11x1x
2026-05-08 5:21 [PATCH net-next v3 0/5] net: lan743x: Add SFP support for PCI11x1x Thangaraj Samynathan
` (2 preceding siblings ...)
2026-05-08 5:21 ` [PATCH net-next v3 3/5] net: lan743x: Add support to software-nodes for SFP Thangaraj Samynathan
@ 2026-05-08 5:21 ` Thangaraj Samynathan
2026-05-08 5:21 ` [PATCH net-next v3 5/5] net: lan743x: Add PCS/XPCS support for SFP on PCI11x1x Thangaraj Samynathan
4 siblings, 0 replies; 6+ messages in thread
From: Thangaraj Samynathan @ 2026-05-08 5:21 UTC (permalink / raw)
To: netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, bryan.whitehead,
UNGLinuxDriver, linux, linux-kernel
Register an SFP platform device when SFP support is enabled on PCI11x1x
platforms.
Use the software node describing the SFP cage as the firmware node
for the platform device. Associate the I2C adapter with its
corresponding software node for SFP module management over I2C.
Register the SFP platform device during probe and unregister it during
driver cleanup.
Signed-off-by: Thangaraj Samynathan <thangaraj.s@microchip.com>
---
drivers/net/ethernet/microchip/Kconfig | 1 +
drivers/net/ethernet/microchip/lan743x_main.c | 51 ++++++++++++++++++-
drivers/net/ethernet/microchip/lan743x_main.h | 2 +
3 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
index a83db3c7404f..9857053dabf8 100644
--- a/drivers/net/ethernet/microchip/Kconfig
+++ b/drivers/net/ethernet/microchip/Kconfig
@@ -52,6 +52,7 @@ config LAN743X
select PHYLINK
select I2C_PCI1XXXX
select GP_PCI1XXXX
+ select SFP
help
Support for the Microchip LAN743x and PCI11x1x families of PCI
Express Ethernet devices
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index b90b35cef2e6..88a2d11552f8 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -3066,6 +3066,31 @@ static int lan743x_swnodes_register(struct lan743x_adapter *adapter)
return software_node_register_node_group(nodes->group);
}
+static int lan743x_sfp_register(struct lan743x_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct platform_device_info sfp_info;
+ struct platform_device *sfp_dev;
+
+ memset(&sfp_info, 0, sizeof(sfp_info));
+ sfp_info.parent = &adapter->pdev->dev;
+ sfp_info.fwnode = software_node_fwnode(adapter->nodes->group[SWNODE_SFP]);
+ sfp_info.name = "sfp";
+ sfp_info.id = (pdev->bus->number << 8) | pdev->devfn;
+ sfp_dev = platform_device_register_full(&sfp_info);
+ if (IS_ERR(sfp_dev)) {
+ netif_err(adapter, drv, adapter->netdev,
+ "Failed to register SFP device\n");
+ return PTR_ERR(sfp_dev);
+ }
+
+ adapter->sfp_dev = sfp_dev;
+ netif_dbg(adapter, drv, adapter->netdev,
+ "SFP platform device registered");
+
+ return 0;
+}
+
static int lan743x_phylink_sgmii_config(struct lan743x_adapter *adapter)
{
u32 sgmii_ctl;
@@ -3682,6 +3707,12 @@ static void lan743x_destroy_phylink(struct lan743x_adapter *adapter)
static void lan743x_full_cleanup(struct lan743x_adapter *adapter)
{
unregister_netdev(adapter->netdev);
+ if (adapter->sfp_dev) {
+ platform_device_unregister(adapter->sfp_dev);
+ adapter->sfp_dev = NULL;
+ }
+ if (adapter->i2c_adap)
+ adapter->i2c_adap = NULL;
lan743x_destroy_phylink(adapter);
lan743x_mdiobus_cleanup(adapter);
@@ -3909,11 +3940,29 @@ static int lan743x_pcidev_probe(struct pci_dev *pdev,
goto cleanup_mdiobus;
}
+ if (adapter->is_sfp_support_en) {
+ adapter->i2c_adap->dev.fwnode =
+ software_node_fwnode(adapter->nodes->group[SWNODE_I2C]);
+
+ ret = lan743x_sfp_register(adapter);
+ if (ret < 0) {
+ netif_err(adapter, probe, netdev,
+ "failed to sfp register (%d)\n", ret);
+ goto cleanup_phylink;
+ }
+ }
+
ret = register_netdev(adapter->netdev);
if (ret < 0)
- goto cleanup_phylink;
+ goto cleanup_sfp;
return 0;
+cleanup_sfp:
+ if (adapter->sfp_dev) {
+ platform_device_unregister(adapter->sfp_dev);
+ adapter->sfp_dev = NULL;
+ }
+
cleanup_phylink:
lan743x_destroy_phylink(adapter);
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index 48db45d41502..fd1c2842b4c8 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -9,6 +9,7 @@
#include <linux/i2c.h>
#include <linux/phy.h>
#include <linux/phylink.h>
+#include <linux/platform_device.h>
#include <linux/property.h>
#include "lan743x_ptp.h"
@@ -1173,6 +1174,7 @@ struct lan743x_adapter {
int rx_tstamp_filter;
struct lan743x_sw_nodes *nodes;
struct i2c_adapter *i2c_adap;
+ struct platform_device *sfp_dev;
};
#define LAN743X_COMPONENT_FLAG_RX(channel) BIT(20 + (channel))
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH net-next v3 5/5] net: lan743x: Add PCS/XPCS support for SFP on PCI11x1x
2026-05-08 5:21 [PATCH net-next v3 0/5] net: lan743x: Add SFP support for PCI11x1x Thangaraj Samynathan
` (3 preceding siblings ...)
2026-05-08 5:21 ` [PATCH net-next v3 4/5] net: lan743x: Register SFP platform device for PCI11x1x Thangaraj Samynathan
@ 2026-05-08 5:21 ` Thangaraj Samynathan
4 siblings, 0 replies; 6+ messages in thread
From: Thangaraj Samynathan @ 2026-05-08 5:21 UTC (permalink / raw)
To: netdev
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, bryan.whitehead,
UNGLinuxDriver, linux, linux-kernel
Add a PCS MII bus and XPCS instance to support SFP modules on PCI11x1x
platforms.
Register a dedicated mdiobus for PCS access when SFP support is enabled
and initialize it with C45 read/write callbacks. Implement generic PCS
read/write functions that use the internal SGMII access functions for
the PCS.
Integrate the XPCS instance with phylink by providing a mac_select_pcs
callback. Support SGMII and 2.5GBASE-X interfaces in phylink, allowing
proper link configuration for SFP modules.
Cleanup the PCS mdiobus and XPCS instance during driver removal. Update
adapter structure to hold PCS mdiobus and XPCS references.
Signed-off-by: Thangaraj Samynathan <thangaraj.s@microchip.com>
---
drivers/net/ethernet/microchip/lan743x_main.c | 86 ++++++++++++++++++-
drivers/net/ethernet/microchip/lan743x_main.h | 3 +
2 files changed, 86 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 88a2d11552f8..485fbc678481 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -15,7 +15,6 @@
#include <linux/rtnetlink.h>
#include <linux/iopoll.h>
#include <linux/crc16.h>
-#include <linux/phylink.h>
#include "lan743x_main.h"
#include "lan743x_ethtool.h"
@@ -1137,6 +1136,28 @@ static int lan743x_get_lsd(int speed, int duplex, u8 mss)
return lsd;
}
+static int pci11x1x_pcs_read(struct mii_bus *bus, int addr, int devnum,
+ int regnum)
+{
+ struct lan743x_adapter *adapter = bus->priv;
+
+ if (addr)
+ return -EOPNOTSUPP;
+
+ return lan743x_sgmii_read(adapter, devnum, regnum);
+}
+
+static int pci11x1x_pcs_write(struct mii_bus *bus, int addr, int devnum,
+ int regnum, u16 val)
+{
+ struct lan743x_adapter *adapter = bus->priv;
+
+ if (addr)
+ return -EOPNOTSUPP;
+
+ return lan743x_sgmii_write(adapter, devnum, regnum, val);
+}
+
static int lan743x_sgmii_mpll_set(struct lan743x_adapter *adapter,
u16 baud)
{
@@ -3199,6 +3220,18 @@ static void lan743x_mac_eee_enable(struct lan743x_adapter *adapter, bool enable)
lan743x_csr_write(adapter, MAC_CR, mac_cr);
}
+static struct phylink_pcs *lan743x_phylink_mac_select(struct phylink_config *config,
+ phy_interface_t interface)
+{
+ struct net_device *netdev = to_net_dev(config->dev);
+ struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+ if (adapter->xpcs)
+ return adapter->xpcs;
+
+ return NULL;
+}
+
static void lan743x_phylink_mac_config(struct phylink_config *config,
unsigned int link_an_mode,
const struct phylink_link_state *state)
@@ -3330,6 +3363,7 @@ static const struct phylink_mac_ops lan743x_phylink_mac_ops = {
.mac_link_up = lan743x_phylink_mac_link_up,
.mac_disable_tx_lpi = lan743x_mac_disable_tx_lpi,
.mac_enable_tx_lpi = lan743x_mac_enable_tx_lpi,
+ .mac_select_pcs = lan743x_phylink_mac_select,
};
static int lan743x_phylink_create(struct lan743x_adapter *adapter)
@@ -3353,6 +3387,7 @@ static int lan743x_phylink_create(struct lan743x_adapter *adapter)
switch (adapter->phy_interface) {
case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_2500BASEX:
__set_bit(PHY_INTERFACE_MODE_SGMII,
adapter->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_1000BASEX,
@@ -3416,12 +3451,13 @@ static int lan743x_phylink_connect(struct lan743x_adapter *adapter)
struct device_node *dn = adapter->pdev->dev.of_node;
struct net_device *dev = adapter->netdev;
struct phy_device *phydev;
- int ret;
+ int ret = 0;
if (dn)
ret = phylink_of_phy_connect(adapter->phylink, dn, 0);
- if (!dn || (ret && !lan743x_phy_handle_exists(dn))) {
+ if (!adapter->is_sfp_support_en &&
+ (!dn || (ret && !lan743x_phy_handle_exists(dn)))) {
phydev = phy_find_first(adapter->mdiobus);
if (phydev) {
/* attach the mac to the phy */
@@ -3694,6 +3730,9 @@ static void lan743x_hardware_cleanup(struct lan743x_adapter *adapter)
static void lan743x_mdiobus_cleanup(struct lan743x_adapter *adapter)
{
+ if (adapter->xpcs)
+ xpcs_destroy_pcs(adapter->xpcs);
+
mdiobus_unregister(adapter->mdiobus);
}
@@ -3806,6 +3845,42 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
return 0;
}
+static int lan743x_pcs_mdiobus_init(struct lan743x_adapter *adapter)
+{
+ struct phylink_pcs *pcs;
+ int ret;
+
+ adapter->pcs_mdiobus = devm_mdiobus_alloc(&adapter->pdev->dev);
+ if (!(adapter->pcs_mdiobus)) {
+ ret = -ENOMEM;
+ goto return_error;
+ }
+
+ adapter->pcs_mdiobus->priv = (void *)adapter;
+ adapter->pcs_mdiobus->read_c45 = pci11x1x_pcs_read;
+ adapter->pcs_mdiobus->write_c45 = pci11x1x_pcs_write;
+ adapter->pcs_mdiobus->name = "lan743x-pcs-mdiobus-c45";
+ netif_dbg(adapter, drv, adapter->netdev, "lan743x-pcs-mdiobus-c45\n");
+ snprintf(adapter->pcs_mdiobus->id, MII_BUS_ID_SIZE, "pci-pcs-%s", pci_name(adapter->pdev));
+
+ if (!adapter->phy_interface)
+ lan743x_phy_interface_select(adapter);
+
+ pcs = xpcs_create_pcs_mdiodev(adapter->pcs_mdiobus, 0);
+ if (IS_ERR(pcs)) {
+ netdev_err(adapter->netdev, "failed to create xpcs\n");
+ ret = PTR_ERR(pcs);
+ goto return_error;
+ }
+
+ adapter->xpcs = pcs;
+ return 0;
+
+return_error:
+ mdiobus_free(adapter->pcs_mdiobus);
+ return ret;
+}
+
static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
{
int ret;
@@ -3927,6 +4002,11 @@ static int lan743x_pcidev_probe(struct pci_dev *pdev,
if (ret)
goto cleanup_hardware;
+ if (adapter->is_sfp_support_en) {
+ ret = lan743x_pcs_mdiobus_init(adapter);
+ if (ret)
+ goto cleanup_hardware;
+ }
adapter->netdev->netdev_ops = &lan743x_netdev_ops;
adapter->netdev->ethtool_ops = &lan743x_ethtool_ops;
adapter->netdev->features = NETIF_F_SG | NETIF_F_TSO |
diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
index fd1c2842b4c8..9740c2628f94 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.h
+++ b/drivers/net/ethernet/microchip/lan743x_main.h
@@ -8,6 +8,7 @@
#include <linux/gpio/machine.h>
#include <linux/i2c.h>
#include <linux/phy.h>
+#include <linux/pcs/pcs-xpcs.h>
#include <linux/phylink.h>
#include <linux/platform_device.h>
#include <linux/property.h>
@@ -1132,6 +1133,7 @@ struct lan743x_sw_nodes {
struct lan743x_adapter {
struct net_device *netdev;
struct mii_bus *mdiobus;
+ struct mii_bus *pcs_mdiobus;
int msg_enable;
#ifdef CONFIG_PM
u32 wolopts;
@@ -1169,6 +1171,7 @@ struct lan743x_adapter {
u32 flags;
u32 hw_cfg;
phy_interface_t phy_interface;
+ struct phylink_pcs *xpcs;
struct phylink *phylink;
struct phylink_config phylink_config;
int rx_tstamp_filter;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread