public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/2] phy: Add generic PHY driver used by MACB/GEM on EyeQ5
@ 2026-02-25 16:54 Théo Lebrun
  2026-02-25 16:54 ` [PATCH v7 1/2] phy: sort Kconfig and Makefile Théo Lebrun
  2026-02-25 16:54 ` [PATCH v7 2/2] phy: Add driver for EyeQ5 Ethernet PHY wrapper Théo Lebrun
  0 siblings, 2 replies; 6+ messages in thread
From: Théo Lebrun @ 2026-02-25 16:54 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong
  Cc: linux-phy, linux-kernel, linux-mips, Vladimir Kondratiev,
	Gregory CLEMENT, Benoît Monin, Tawfik Bayouk,
	Thomas Petazzoni, Luca Ceresoli, Théo Lebrun

EyeQ5 SoCs integrate two GEM instances. A system-controller register
region named "OLB" has some control over the Ethernet PHY integration.

Extend the current OLB ecosystem with a new generic PHY driver.
 - OLB is carried by one main platform driver: clk-eyeq.
 - It instantiates auxiliary devices: reset-eyeq & pinctrl-eyeq5.
 - We add a new one: phy-eyeq5-eth.

About related patches:

 - The MACB series [1] has been merged in v6.19-rc1. It makes MACB
   consume a generic PHY from devicetree with the EyeQ5 compatible.

 - clk patches are incoming to make clk-eyeq instantiate this new
   auxiliary device. They also ensure we get a dev->of_node assigned.
   Patches used to be [2] in the same series.

 - MIPS patches are incoming to add MACB/GEM instances in devicetree and
   their associated PHYs. They also update dt-bindings to reflect this
   new feature OLB provides. Patches used to be [2] in the same series.

Have a nice day,
Thanks!
Théo

[0]: https://lore.kernel.org/lkml/20250627-macb-v2-15-ff8207d0bb77@bootlin.com/
[1]: https://lore.kernel.org/lkml/20251022-macb-eyeq5-v2-0-7c140abb0581@bootlin.com/
[2]: https://lore.kernel.org/all/20260127-macb-phy-v6-0-cdd840588188@bootlin.com/

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
Changes in v7:
- Separate PHY / clk / MIPS patches into three series.
- Implement phy_validate().
- phy_power_on() now supports being called without a prior
  phy_set_mode() because at probe we read the hardware state to
  initialise inst->phy_instance.
- phy_set_mode() now support being called while the PHY is powered on.
- Add sgmii_support bool for each PHY instance to reject SGMII
  configuration on PHY 1 which only supports RGMII.
- Drop dev_dbg() calls.
- Drop readl(gp) in phy_init().
- Replace inst->priv field by inst->dev; that is the only value we need
  from the driver private data. Drop priv->dev field that is unused.
- Call into phy_exit() from phy_init() as the sequence is the same.
  Add comment to explain the reasoning.
- Take Reviewed-by: Luca on "phy: sort Kconfig and Makefile".
- Rebase onto v7.0-rc1 and test on EyeQ5. Only diff to report:
  PHY_COMMON_PROPS and PHY_COMMON_PROPS_TEST are kept at the top in the
  sorting patch; we do not strictly respect an alphabetical ordering.
- Link to v6: https://lore.kernel.org/r/20260127-macb-phy-v6-0-cdd840588188@bootlin.com

Changes in v6:
- Rebase upon v6.19-rc7; nothing to report.
- Add new patch "phy: sort Kconfig and Makefile".
- phy-eyeq5-eth: drop useless explicit __iomem cast to
  dev_get_platdata() return value.
- I did *not* drop the Kconfig `default MACH_EYEQ5` nor driver
  `dev_dbg()`. I think both are useful and should be kept. See
  last revision discussion here:
  https://lore.kernel.org/lkml/DFGSMN8268O0.33TYCQDBVHUHZ@bootlin.com/
- Link to v5: https://lore.kernel.org/r/20251215-macb-phy-v5-0-a9dfea39da34@bootlin.com

Changes in v5:
- phy-eyeq5-eth:
  - fix #includes: add delay, gfp_types, module and drop array_size,
    bug, cleanup, container_of, lockdep, mutex.
  - eq5_phy_xlate(): avoid magic value, use EQ5_PHY_COUNT.
  - use dev_err_probe() in error cases of devm_phy_create() and
    devm_of_phy_provider_register().
- 3x Reviewed-by: Luca Ceresoli.
- Add Neil Armstrong to Cc as new PHY subsystem reviewer.
- Rebase on v6.19-rc1, tested on hardware, no changes.
- Link to v4: https://lore.kernel.org/r/20251124-macb-phy-v4-0-955c625a81a7@bootlin.com

Changes in v4:
- Append my SoB to Jerome's patch:
  [PATCH v4 3/7] clk: eyeq: use the auxiliary device creation helper
- Rebase on net-next & linux-{clk,mips,phy}. Nothing to report.
- Link to v3: https://lore.kernel.org/r/20251119-macb-phy-v3-0-e9a7be186a33@bootlin.com

Changes in v3:
- Take Philipp Zabel's Reviewed-by & Acked-by trailers on reset patch.
- Take Thomas Bogendoerfer's two Acked-by trailers on DT patches.
- Rebase on net-next & test on target. Nothing to report.
- Link to v2: https://lore.kernel.org/r/20251101-macb-phy-v2-0-c1519eef16d3@bootlin.com

Changes in v2:
- Take Acked-by: Conor Dooley on dt-bindings-patch.
- s/%ld/%tu/ for printing ptrdiff_t; warnings on 32-bit archs.
  Reported by NIPA's netdev/build_32bit test.
  https://patchwork.kernel.org/project/netdevbpf/patch/20251021-macb-eyeq5-v1-7-3b0b5a9d2f85@bootlin.com/
  https://netdev.bots.linux.dev/static/nipa/1014126/14277857/build_32bit/stderr
- Link to v1: https://lore.kernel.org/r/20251022-macb-phy-v1-0-f29f28fae721@bootlin.com

Changes since MACB V1:
- Drop the old "mobileye,olb" properties from DT patches; found while
  running dtbs_check and dt_binding_check.
- Drop all patches targeting net-next. That is MACB dt-bindings patch
  and MACB driver code. See there here [1].
- Link to v1: https://lore.kernel.org/lkml/20251021-macb-eyeq5-v1-0-3b0b5a9d2f85@bootlin.com/

Past versions of MACB patches:
 - March 2025: [PATCH net-next 00/13] Support the Cadence MACB/GEM
   instances on Mobileye EyeQ5 SoCs
   https://lore.kernel.org/lkml/20250321-macb-v1-0-537b7e37971d@bootlin.com/
 - June 2025: [PATCH net-next v2 00/18] Support the Cadence MACB/GEM
   instances on Mobileye EyeQ5 SoCs
   https://lore.kernel.org/lkml/20250627-macb-v2-0-ff8207d0bb77@bootlin.com/
 - August 2025: [PATCH net v3 00/16] net: macb: various fixes & cleanup
   https://lore.kernel.org/lkml/20250808-macb-fixes-v3-0-08f1fcb5179f@bootlin.com/

---
Théo Lebrun (2):
      phy: sort Kconfig and Makefile
      phy: Add driver for EyeQ5 Ethernet PHY wrapper

 MAINTAINERS                 |   1 +
 drivers/phy/Kconfig         |  99 +++++++++--------
 drivers/phy/Makefile        |   9 +-
 drivers/phy/phy-eyeq5-eth.c | 261 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 323 insertions(+), 47 deletions(-)
---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20251022-macb-phy-21bc4e1dfbb7

Best regards,
-- 
Théo Lebrun <theo.lebrun@bootlin.com>


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

* [PATCH v7 1/2] phy: sort Kconfig and Makefile
  2026-02-25 16:54 [PATCH v7 0/2] phy: Add generic PHY driver used by MACB/GEM on EyeQ5 Théo Lebrun
@ 2026-02-25 16:54 ` Théo Lebrun
  2026-02-27 13:55   ` Vinod Koul
  2026-02-25 16:54 ` [PATCH v7 2/2] phy: Add driver for EyeQ5 Ethernet PHY wrapper Théo Lebrun
  1 sibling, 1 reply; 6+ messages in thread
From: Théo Lebrun @ 2026-02-25 16:54 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong
  Cc: linux-phy, linux-kernel, linux-mips, Vladimir Kondratiev,
	Gregory CLEMENT, Benoît Monin, Tawfik Bayouk,
	Thomas Petazzoni, Luca Ceresoli, Théo Lebrun

Neither Kconfig nor Makefile are sorted; reorder them.

$ diff -U100 <(grep ^config drivers/phy/Kconfig) \
             <(grep ^config drivers/phy/Kconfig | sort)

$ diff -U100 <(grep ^obj-\\$ drivers/phy/Makefile) \
             <(grep ^obj-\\$ drivers/phy/Makefile | sort)

PHY_COMMON_PROPS{,_TEST} are kept at the top which does not respect
sorting order.

Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 drivers/phy/Kconfig  | 86 ++++++++++++++++++++++++++--------------------------
 drivers/phy/Makefile |  8 ++---
 2 files changed, 47 insertions(+), 47 deletions(-)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 02467dfd4fb0..c86e90027443 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -47,6 +47,26 @@ config GENERIC_PHY_MIPI_DPHY
 	  Provides a number of helpers a core functions for MIPI D-PHY
 	  drivers to us.
 
+config PHY_AIROHA_PCIE
+	tristate "Airoha PCIe-PHY Driver"
+	depends on ARCH_AIROHA || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Say Y here to add support for Airoha PCIe PHY driver.
+	  This driver create the basic PHY instance and provides initialize
+	  callback for PCIe GEN3 port.
+
+config PHY_CAN_TRANSCEIVER
+	tristate "CAN transceiver PHY"
+	select GENERIC_PHY
+	select MULTIPLEXER
+	help
+	  This option enables support for CAN transceivers as a PHY. This
+	  driver provides function for putting the transceivers in various
+	  functional modes using gpios and sets the attribute max link
+	  rate, for CAN drivers.
+
 config PHY_GOOGLE_USB
 	tristate "Google Tensor SoC USB PHY driver"
 	select GENERIC_PHY
@@ -69,6 +89,17 @@ config PHY_LPC18XX_USB_OTG
 	  This driver is need for USB0 support on LPC18xx/43xx and takes
 	  care of enabling and clock setup.
 
+config PHY_NXP_PTN3222
+	tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
+	depends on I2C
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Enable this to support NXP PTN3222 1-port eUSB2 to USB2 Redriver.
+	  This redriver performs translation between eUSB2 and USB2 signalling
+	  schemes. It supports all three USB 2.0 data rates: Low Speed, Full
+	  Speed and High Speed.
+
 config PHY_PISTACHIO_USB
 	tristate "IMG Pistachio USB2.0 PHY driver"
 	depends on MIPS || COMPILE_TEST
@@ -84,6 +115,18 @@ config PHY_SNPS_EUSB2
 	  Enable support for the USB high-speed SNPS eUSB2 phy on select
 	  SoCs. The PHY is usually paired with a Synopsys DWC3 USB controller.
 
+config PHY_SPACEMIT_K1_PCIE
+	tristate "PCIe and combo PHY driver for the SpacemiT K1 SoC"
+	depends on ARCH_SPACEMIT || COMPILE_TEST
+	depends on COMMON_CLK
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+	default ARCH_SPACEMIT
+	help
+	  Enable support for the PCIe and USB 3 combo PHY and two
+	  PCIe-only PHYs used in the SpacemiT K1 SoC.
+
 config PHY_XGENE
 	tristate "APM X-Gene 15Gbps PHY support"
 	depends on HAS_IOMEM && OF && (ARCH_XGENE || COMPILE_TEST)
@@ -103,49 +146,6 @@ config USB_LGM_PHY
 	  interface to interact with USB GEN-II and USB 3.x PHY that is part
 	  of the Intel network SOC.
 
-config PHY_CAN_TRANSCEIVER
-	tristate "CAN transceiver PHY"
-	select GENERIC_PHY
-	select MULTIPLEXER
-	help
-	  This option enables support for CAN transceivers as a PHY. This
-	  driver provides function for putting the transceivers in various
-	  functional modes using gpios and sets the attribute max link
-	  rate, for CAN drivers.
-
-config PHY_AIROHA_PCIE
-	tristate "Airoha PCIe-PHY Driver"
-	depends on ARCH_AIROHA || COMPILE_TEST
-	depends on OF
-	select GENERIC_PHY
-	help
-	  Say Y here to add support for Airoha PCIe PHY driver.
-	  This driver create the basic PHY instance and provides initialize
-	  callback for PCIe GEN3 port.
-
-config PHY_NXP_PTN3222
-	tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
-	depends on I2C
-	depends on OF
-	select GENERIC_PHY
-	help
-	  Enable this to support NXP PTN3222 1-port eUSB2 to USB2 Redriver.
-	  This redriver performs translation between eUSB2 and USB2 signalling
-	  schemes. It supports all three USB 2.0 data rates: Low Speed, Full
-	  Speed and High Speed.
-
-config PHY_SPACEMIT_K1_PCIE
-	tristate "PCIe and combo PHY driver for the SpacemiT K1 SoC"
-	depends on ARCH_SPACEMIT || COMPILE_TEST
-	depends on COMMON_CLK
-	depends on HAS_IOMEM
-	depends on OF
-	select GENERIC_PHY
-	default ARCH_SPACEMIT
-	help
-	  Enable support for the PCIe and USB 3 combo PHY and two
-	  PCIe-only PHYs used in the SpacemiT K1 SoC.
-
 source "drivers/phy/allwinner/Kconfig"
 source "drivers/phy/amlogic/Kconfig"
 source "drivers/phy/apple/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index a648c2e02a83..4c07926bc47b 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -7,16 +7,16 @@ obj-$(CONFIG_PHY_COMMON_PROPS)		+= phy-common-props.o
 obj-$(CONFIG_PHY_COMMON_PROPS_TEST)	+= phy-common-props-test.o
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
 obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY)	+= phy-core-mipi-dphy.o
+obj-$(CONFIG_PHY_AIROHA_PCIE)		+= phy-airoha-pcie.o
 obj-$(CONFIG_PHY_CAN_TRANSCEIVER)	+= phy-can-transceiver.o
 obj-$(CONFIG_PHY_GOOGLE_USB)		+= phy-google-usb.o
 obj-$(CONFIG_PHY_LPC18XX_USB_OTG)	+= phy-lpc18xx-usb-otg.o
-obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
+obj-$(CONFIG_PHY_NXP_PTN3222)		+= phy-nxp-ptn3222.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
 obj-$(CONFIG_PHY_SNPS_EUSB2)		+= phy-snps-eusb2.o
-obj-$(CONFIG_USB_LGM_PHY)		+= phy-lgm-usb.o
-obj-$(CONFIG_PHY_AIROHA_PCIE)		+= phy-airoha-pcie.o
-obj-$(CONFIG_PHY_NXP_PTN3222)		+= phy-nxp-ptn3222.o
 obj-$(CONFIG_PHY_SPACEMIT_K1_PCIE)	+= phy-spacemit-k1-pcie.o
+obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
+obj-$(CONFIG_USB_LGM_PHY)		+= phy-lgm-usb.o
 obj-$(CONFIG_GENERIC_PHY)		+= allwinner/	\
 					   amlogic/	\
 					   apple/	\

-- 
2.53.0


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

* [PATCH v7 2/2] phy: Add driver for EyeQ5 Ethernet PHY wrapper
  2026-02-25 16:54 [PATCH v7 0/2] phy: Add generic PHY driver used by MACB/GEM on EyeQ5 Théo Lebrun
  2026-02-25 16:54 ` [PATCH v7 1/2] phy: sort Kconfig and Makefile Théo Lebrun
@ 2026-02-25 16:54 ` Théo Lebrun
  2026-02-27 17:14   ` Vladimir Oltean
  1 sibling, 1 reply; 6+ messages in thread
From: Théo Lebrun @ 2026-02-25 16:54 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong
  Cc: linux-phy, linux-kernel, linux-mips, Vladimir Kondratiev,
	Gregory CLEMENT, Benoît Monin, Tawfik Bayouk,
	Thomas Petazzoni, Luca Ceresoli, Théo Lebrun

EyeQ5 embeds a system-controller called OLB. It features many unrelated
registers, and some of those are registers used to configure the
integration of the RGMII/SGMII Cadence PHY used by MACB/GEM instances.

Wrap in a neat generic PHY provider, exposing two PHYs with standard
phy_init() / phy_set_mode() / phy_power_on() operations.

Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
 MAINTAINERS                 |   1 +
 drivers/phy/Kconfig         |  13 +++
 drivers/phy/Makefile        |   1 +
 drivers/phy/phy-eyeq5-eth.c | 261 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 276 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 55af015174a5..6bc2ae3bbd4b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17812,6 +17812,7 @@ F:	arch/mips/boot/dts/mobileye/
 F:	arch/mips/configs/eyeq5_defconfig
 F:	arch/mips/mobileye/board-epm5.its.S
 F:	drivers/clk/clk-eyeq.c
+F:	drivers/phy/phy-eyeq5-eth.c
 F:	drivers/pinctrl/pinctrl-eyeq5.c
 F:	drivers/reset/reset-eyeq.c
 F:	include/dt-bindings/clock/mobileye,eyeq5-clk.h
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index c86e90027443..2c9f3272b320 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -67,6 +67,19 @@ config PHY_CAN_TRANSCEIVER
 	  functional modes using gpios and sets the attribute max link
 	  rate, for CAN drivers.
 
+config PHY_EYEQ5_ETH
+	tristate "Ethernet PHY Driver on EyeQ5"
+	depends on OF
+	depends on MACH_EYEQ5 || COMPILE_TEST
+	select AUXILIARY_BUS
+	select GENERIC_PHY
+	default MACH_EYEQ5
+	help
+	  Enable this to support the Ethernet PHY integrated on EyeQ5.
+	  It supports both RGMII and SGMII. Registers are located in a
+	  shared register region called OLB. If M is selected, the
+	  module will be called phy-eyeq5-eth.
+
 config PHY_GOOGLE_USB
 	tristate "Google Tensor SoC USB PHY driver"
 	select GENERIC_PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 4c07926bc47b..57178c17752c 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
 obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY)	+= phy-core-mipi-dphy.o
 obj-$(CONFIG_PHY_AIROHA_PCIE)		+= phy-airoha-pcie.o
 obj-$(CONFIG_PHY_CAN_TRANSCEIVER)	+= phy-can-transceiver.o
+obj-$(CONFIG_PHY_EYEQ5_ETH)		+= phy-eyeq5-eth.o
 obj-$(CONFIG_PHY_GOOGLE_USB)		+= phy-google-usb.o
 obj-$(CONFIG_PHY_LPC18XX_USB_OTG)	+= phy-lpc18xx-usb-otg.o
 obj-$(CONFIG_PHY_NXP_PTN3222)		+= phy-nxp-ptn3222.o
diff --git a/drivers/phy/phy-eyeq5-eth.c b/drivers/phy/phy-eyeq5-eth.c
new file mode 100644
index 000000000000..883ae82d9434
--- /dev/null
+++ b/drivers/phy/phy-eyeq5-eth.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/gfp_types.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define EQ5_PHY_COUNT	2
+
+#define EQ5_PHY0_GP	0x128
+#define EQ5_PHY1_GP	0x12c
+#define EQ5_PHY0_SGMII	0x134
+#define EQ5_PHY1_SGMII	0x138
+
+#define EQ5_GP_TX_SWRST_DIS	BIT(0)		// Tx SW reset
+#define EQ5_GP_TX_M_CLKE	BIT(1)		// Tx M clock enable
+#define EQ5_GP_SYS_SWRST_DIS	BIT(2)		// Sys SW reset
+#define EQ5_GP_SYS_M_CLKE	BIT(3)		// Sys clock enable
+#define EQ5_GP_SGMII_MODE	BIT(4)		// SGMII mode
+#define EQ5_GP_RGMII_DRV	GENMASK(8, 5)	// RGMII drive strength
+
+#define EQ5_SGMII_PWR_EN	BIT(0)
+#define EQ5_SGMII_RST_DIS	BIT(1)
+#define EQ5_SGMII_PLL_EN	BIT(2)
+#define EQ5_SGMII_SIG_DET_SW	BIT(3)
+#define EQ5_SGMII_PWR_STATE	BIT(4)
+#define EQ5_SGMII_PLL_ACK	BIT(18)
+#define EQ5_SGMII_PWR_STATE_ACK	GENMASK(24, 20)
+
+struct eq5_phy_inst {
+	struct device		*dev;
+	struct phy		*phy;
+	void __iomem		*gp, *sgmii;
+	phy_interface_t		phy_interface;
+	bool			sgmii_support;
+};
+
+struct eq5_phy_private {
+	struct eq5_phy_inst	phys[EQ5_PHY_COUNT];
+};
+
+static int eq5_phy_exit(struct phy *phy)
+{
+	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
+
+	writel(0, inst->gp);
+	writel(0, inst->sgmii);
+	udelay(5); /* settling time */
+	return 0;
+}
+
+static int eq5_phy_init(struct phy *phy)
+{
+	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
+	u32 reg;
+
+	/*
+	 * Hardware stops listening to our instructions once it is started.
+	 * It must be reset to reconfigure it.
+	 */
+	eq5_phy_exit(phy);
+
+	reg = EQ5_GP_TX_SWRST_DIS | EQ5_GP_TX_M_CLKE |
+	      EQ5_GP_SYS_SWRST_DIS | EQ5_GP_SYS_M_CLKE |
+	      FIELD_PREP(EQ5_GP_RGMII_DRV, 0x9);
+	writel(reg, inst->gp);
+
+	return 0;
+}
+
+static int eq5_phy_power_on(struct phy *phy)
+{
+	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
+	u32 reg;
+
+	if (inst->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+		writel(readl(inst->gp) | EQ5_GP_SGMII_MODE, inst->gp);
+
+		reg = EQ5_SGMII_PWR_EN | EQ5_SGMII_RST_DIS | EQ5_SGMII_PLL_EN;
+		writel(reg, inst->sgmii);
+
+		if (readl_poll_timeout(inst->sgmii, reg,
+				       reg & EQ5_SGMII_PLL_ACK, 1, 100)) {
+			dev_err(inst->dev, "PLL timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		reg = readl(inst->sgmii);
+		reg |= EQ5_SGMII_PWR_STATE | EQ5_SGMII_SIG_DET_SW;
+		writel(reg, inst->sgmii);
+	} else {
+		writel(readl(inst->gp) & ~EQ5_GP_SGMII_MODE, inst->gp);
+		writel(0, inst->sgmii);
+	}
+
+	return 0;
+}
+
+static int eq5_phy_power_off(struct phy *phy)
+{
+	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
+
+	writel(readl(inst->gp) & ~EQ5_GP_SGMII_MODE, inst->gp);
+	writel(0, inst->sgmii);
+
+	return 0;
+}
+
+static int eq5_phy_validate(struct phy *phy, enum phy_mode mode, int submode,
+			    union phy_configure_opts *opts)
+{
+	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
+
+	if (mode != PHY_MODE_ETHERNET)
+		return -EINVAL;
+
+	if (phy_interface_mode_is_rgmii(submode))
+		return 0;
+
+	if (inst->sgmii_support && submode == PHY_INTERFACE_MODE_SGMII)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int eq5_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
+
+	if (eq5_phy_validate(phy, mode, submode, NULL))
+		return -EOPNOTSUPP;
+
+	if (submode == inst->phy_interface)
+		return 0;
+
+	inst->phy_interface = submode;
+
+	if (phy->power_count) {
+		eq5_phy_init(phy);
+		return eq5_phy_power_on(phy);
+	}
+
+	return 0;
+}
+
+static const struct phy_ops eq5_phy_ops = {
+	.init		= eq5_phy_init,
+	.exit		= eq5_phy_exit,
+	.power_on	= eq5_phy_power_on,
+	.power_off	= eq5_phy_power_off,
+	.set_mode	= eq5_phy_set_mode,
+	.validate	= eq5_phy_validate,
+};
+
+static struct phy *eq5_phy_xlate(struct device *dev,
+				 const struct of_phandle_args *args)
+{
+	struct eq5_phy_private *priv = dev_get_drvdata(dev);
+
+	if (args->args_count != 1 || args->args[0] >= EQ5_PHY_COUNT)
+		return ERR_PTR(-EINVAL);
+
+	return priv->phys[args->args[0]].phy;
+}
+
+static int eq5_phy_probe_phy(struct device *dev, struct eq5_phy_private *priv,
+			     unsigned int index, void __iomem *base,
+			     unsigned int gp, unsigned int sgmii,
+			     bool sgmii_support)
+{
+	struct eq5_phy_inst *inst = &priv->phys[index];
+	struct phy *phy;
+
+	phy = devm_phy_create(dev, dev->of_node, &eq5_phy_ops);
+	if (IS_ERR(phy))
+		return dev_err_probe(dev, PTR_ERR(phy),
+				     "failed to create PHY %u\n", index);
+
+	inst->dev = dev;
+	inst->phy = phy;
+	inst->gp = base + gp;
+	inst->sgmii = base + sgmii;
+	inst->sgmii_support = sgmii_support;
+	phy_set_drvdata(phy, inst);
+
+	/*
+	 * Init inst->phy_interface based on probe hardware state, allowing
+	 * consumers to power us on without first setting the mode.
+	 */
+	if (sgmii_support && (readl(inst->gp) & EQ5_GP_SGMII_MODE))
+		inst->phy_interface = PHY_INTERFACE_MODE_SGMII;
+	else
+		inst->phy_interface = PHY_INTERFACE_MODE_RGMII;
+
+	return 0;
+}
+
+static int eq5_phy_probe(struct auxiliary_device *adev,
+			 const struct auxiliary_device_id *id)
+{
+	struct device *dev = &adev->dev;
+	struct phy_provider *provider;
+	struct eq5_phy_private *priv;
+	void __iomem *base;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, priv);
+
+	base = dev_get_platdata(dev);
+
+	ret = eq5_phy_probe_phy(dev, priv, 0, base, EQ5_PHY0_GP,
+				EQ5_PHY0_SGMII, true);
+	if (ret)
+		return ret;
+
+	ret = eq5_phy_probe_phy(dev, priv, 1, base, EQ5_PHY1_GP,
+				EQ5_PHY1_SGMII, false);
+	if (ret)
+		return ret;
+
+	provider = devm_of_phy_provider_register(dev, eq5_phy_xlate);
+	if (IS_ERR(provider))
+		return dev_err_probe(dev, PTR_ERR(provider),
+				     "registering provider failed\n");
+
+	return 0;
+}
+
+static const struct auxiliary_device_id eq5_phy_id_table[] = {
+	{ .name = "clk_eyeq.phy" },
+	{}
+};
+MODULE_DEVICE_TABLE(auxiliary, eq5_phy_id_table);
+
+static struct auxiliary_driver eq5_phy_driver = {
+	.probe = eq5_phy_probe,
+	.id_table = eq5_phy_id_table,
+};
+module_auxiliary_driver(eq5_phy_driver);
+
+MODULE_DESCRIPTION("EyeQ5 Ethernet PHY driver");
+MODULE_AUTHOR("Théo Lebrun <theo.lebrun@bootlin.com>");
+MODULE_LICENSE("GPL");

-- 
2.53.0


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

* Re: [PATCH v7 1/2] phy: sort Kconfig and Makefile
  2026-02-25 16:54 ` [PATCH v7 1/2] phy: sort Kconfig and Makefile Théo Lebrun
@ 2026-02-27 13:55   ` Vinod Koul
  0 siblings, 0 replies; 6+ messages in thread
From: Vinod Koul @ 2026-02-27 13:55 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Neil Armstrong, linux-phy, linux-kernel, linux-mips,
	Vladimir Kondratiev, Gregory CLEMENT, Benoît Monin,
	Tawfik Bayouk, Thomas Petazzoni, Luca Ceresoli

On 25-02-26, 17:54, Théo Lebrun wrote:
> Neither Kconfig nor Makefile are sorted; reorder them.
> 
> $ diff -U100 <(grep ^config drivers/phy/Kconfig) \
>              <(grep ^config drivers/phy/Kconfig | sort)
> 
> $ diff -U100 <(grep ^obj-\\$ drivers/phy/Makefile) \
>              <(grep ^obj-\\$ drivers/phy/Makefile | sort)
> 
> PHY_COMMON_PROPS{,_TEST} are kept at the top which does not respect
> sorting order.
> 
> Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
>  drivers/phy/Kconfig  | 86 ++++++++++++++++++++++++++--------------------------
>  drivers/phy/Makefile |  8 ++---
>  2 files changed, 47 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 02467dfd4fb0..c86e90027443 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -47,6 +47,26 @@ config GENERIC_PHY_MIPI_DPHY
>  	  Provides a number of helpers a core functions for MIPI D-PHY
>  	  drivers to us.
>  
> +config PHY_AIROHA_PCIE
> +	tristate "Airoha PCIe-PHY Driver"
> +	depends on ARCH_AIROHA || COMPILE_TEST
> +	depends on OF
> +	select GENERIC_PHY
> +	help
> +	  Say Y here to add support for Airoha PCIe PHY driver.
> +	  This driver create the basic PHY instance and provides initialize
> +	  callback for PCIe GEN3 port.
> +
> +config PHY_CAN_TRANSCEIVER
> +	tristate "CAN transceiver PHY"
> +	select GENERIC_PHY
> +	select MULTIPLEXER
> +	help
> +	  This option enables support for CAN transceivers as a PHY. This
> +	  driver provides function for putting the transceivers in various
> +	  functional modes using gpios and sets the attribute max link
> +	  rate, for CAN drivers.
> +
>  config PHY_GOOGLE_USB
>  	tristate "Google Tensor SoC USB PHY driver"
>  	select GENERIC_PHY
> @@ -69,6 +89,17 @@ config PHY_LPC18XX_USB_OTG
>  	  This driver is need for USB0 support on LPC18xx/43xx and takes
>  	  care of enabling and clock setup.
>  
> +config PHY_NXP_PTN3222
> +	tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
> +	depends on I2C
> +	depends on OF
> +	select GENERIC_PHY
> +	help
> +	  Enable this to support NXP PTN3222 1-port eUSB2 to USB2 Redriver.
> +	  This redriver performs translation between eUSB2 and USB2 signalling
> +	  schemes. It supports all three USB 2.0 data rates: Low Speed, Full
> +	  Speed and High Speed.
> +
>  config PHY_PISTACHIO_USB
>  	tristate "IMG Pistachio USB2.0 PHY driver"
>  	depends on MIPS || COMPILE_TEST
> @@ -84,6 +115,18 @@ config PHY_SNPS_EUSB2
>  	  Enable support for the USB high-speed SNPS eUSB2 phy on select
>  	  SoCs. The PHY is usually paired with a Synopsys DWC3 USB controller.
>  
> +config PHY_SPACEMIT_K1_PCIE
> +	tristate "PCIe and combo PHY driver for the SpacemiT K1 SoC"
> +	depends on ARCH_SPACEMIT || COMPILE_TEST
> +	depends on COMMON_CLK
> +	depends on HAS_IOMEM
> +	depends on OF
> +	select GENERIC_PHY
> +	default ARCH_SPACEMIT
> +	help
> +	  Enable support for the PCIe and USB 3 combo PHY and two
> +	  PCIe-only PHYs used in the SpacemiT K1 SoC.

I moved this into spacemit directory and while at it notice the file is
not sorted and patched that up.20260223065743.395539-1-vkoul@kernel.org
Sorry I missed this and earlier one

-- 
~Vinod

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

* Re: [PATCH v7 2/2] phy: Add driver for EyeQ5 Ethernet PHY wrapper
  2026-02-25 16:54 ` [PATCH v7 2/2] phy: Add driver for EyeQ5 Ethernet PHY wrapper Théo Lebrun
@ 2026-02-27 17:14   ` Vladimir Oltean
  2026-03-06  9:53     ` Théo Lebrun
  0 siblings, 1 reply; 6+ messages in thread
From: Vladimir Oltean @ 2026-02-27 17:14 UTC (permalink / raw)
  To: Théo Lebrun
  Cc: Vinod Koul, Neil Armstrong, linux-phy, linux-kernel, linux-mips,
	Vladimir Kondratiev, Gregory CLEMENT, Benoît Monin,
	Tawfik Bayouk, Thomas Petazzoni, Luca Ceresoli

On Wed, Feb 25, 2026 at 05:54:41PM +0100, Théo Lebrun wrote:
> +static int eq5_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
> +{
> +	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
> +
> +	if (eq5_phy_validate(phy, mode, submode, NULL))
> +		return -EOPNOTSUPP;

Propagate the phy_validate() return code, don't generate your own.
-EINVAL should be preferable to -EOPNOTSUPP, so that callers can
distinguish between "phy_set_mode() not implemented" and "phy_set_mode()
failed".

(yeah, phy_set_mode() was made optional a while ago, IMO incorrectly,
but that's another story)

> +
> +	if (submode == inst->phy_interface)
> +		return 0;

I think this simple comparison fails to serve its intended purpose
(avoid PHY reset when not changing modes) for RGMII modes, of which
there exist 4 variants.

Maybe:
	if ((phy_interface_mode_is_rgmii(submode) &&
	     phy_interface_mode_is_rgmii(inst->phy_interface)) ||
	    submode == inst->phy_interface)
		return 0;

Does the EyeQ5 platform support internal RGMII delays? If yes, which
layer enables them? The Generic PHY?

> +
> +	inst->phy_interface = submode;
> +
> +	if (phy->power_count) {
> +		eq5_phy_init(phy);
> +		return eq5_phy_power_on(phy);
> +	}
> +
> +	return 0;
> +}

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

* Re: [PATCH v7 2/2] phy: Add driver for EyeQ5 Ethernet PHY wrapper
  2026-02-27 17:14   ` Vladimir Oltean
@ 2026-03-06  9:53     ` Théo Lebrun
  0 siblings, 0 replies; 6+ messages in thread
From: Théo Lebrun @ 2026-03-06  9:53 UTC (permalink / raw)
  To: Vladimir Oltean, Théo Lebrun
  Cc: Vinod Koul, Neil Armstrong, linux-phy, linux-kernel, linux-mips,
	Vladimir Kondratiev, Gregory CLEMENT, Benoît Monin,
	Tawfik Bayouk, Thomas Petazzoni, Luca Ceresoli

Hello Vladimir,

On Fri Feb 27, 2026 at 6:14 PM CET, Vladimir Oltean wrote:
> On Wed, Feb 25, 2026 at 05:54:41PM +0100, Théo Lebrun wrote:
>> +static int eq5_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
>> +{
>> +	struct eq5_phy_inst *inst = phy_get_drvdata(phy);
>> +
>> +	if (eq5_phy_validate(phy, mode, submode, NULL))
>> +		return -EOPNOTSUPP;
>
> Propagate the phy_validate() return code, don't generate your own.
> -EINVAL should be preferable to -EOPNOTSUPP, so that callers can
> distinguish between "phy_set_mode() not implemented" and "phy_set_mode()
> failed".

ACK. I had made the decision to explicitely override the return value
but indeed EOPNOTSUPP isn't the cleverest option. Will fix.

> (yeah, phy_set_mode() was made optional a while ago, IMO incorrectly,
> but that's another story)
>
>> +
>> +	if (submode == inst->phy_interface)
>> +		return 0;
>
> I think this simple comparison fails to serve its intended purpose
> (avoid PHY reset when not changing modes) for RGMII modes, of which
> there exist 4 variants.

Yes!

> Maybe:
> 	if ((phy_interface_mode_is_rgmii(submode) &&
> 	     phy_interface_mode_is_rgmii(inst->phy_interface)) ||
> 	    submode == inst->phy_interface)
> 		return 0;
>
> Does the EyeQ5 platform support internal RGMII delays? If yes, which
> layer enables them? The Generic PHY?

You are on point. We shouldn't care about the RGMII delays inside the
generic PHY driver. What we deal with here is a wrapper to the actual
net PHY behind the scenes. The net PHY is dealing with delays, we can
ignore them in the generic PHY driver.

Will fix, either with your solution or with a custom two state enum that
can do SGMII or RGMII (will represent all RGMII delay variants). I'll
experiment with both and send what looks better.

Thanks,

--
Théo Lebrun, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


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

end of thread, other threads:[~2026-03-06  9:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-25 16:54 [PATCH v7 0/2] phy: Add generic PHY driver used by MACB/GEM on EyeQ5 Théo Lebrun
2026-02-25 16:54 ` [PATCH v7 1/2] phy: sort Kconfig and Makefile Théo Lebrun
2026-02-27 13:55   ` Vinod Koul
2026-02-25 16:54 ` [PATCH v7 2/2] phy: Add driver for EyeQ5 Ethernet PHY wrapper Théo Lebrun
2026-02-27 17:14   ` Vladimir Oltean
2026-03-06  9:53     ` Théo Lebrun

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox