Linux-PHY Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 7/8] PCI: Skip bridge window reads when window is not supported
From: Caleb James DeLisle @ 2026-03-03 21:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel
In-Reply-To: <20260303212345.GA4074959@bhelgaas>


On 03/03/2026 22:23, Bjorn Helgaas wrote:
> On Tue, Mar 03, 2026 at 07:09:47PM +0000, Caleb James DeLisle wrote:
>> pci_read_bridge_io() and pci_read_bridge_mmio_pref() read bridge window
>> registers unconditionally. If the registers are hardwired to zero
>> (not implemented), both base and limit will be 0. Since (0 <= 0) is
>> true, a bogus window [mem 0x00000000-0x000fffff] or [io 0x0000-0x0fff]
>> gets created.
>>
>> pci_read_bridge_windows() already detects unsupported windows by
>> testing register writability and sets io_window/pref_window flags
>> accordingly. Check these flags at the start of pci_read_bridge_io()
>> and pci_read_bridge_mmio_pref() to skip reading registers when the
>> window is not supported.
>>
>> Suggested-by: Bjorn Helgaas <helgaas@kernel.org>
> I think this refers to the conversation at:
>
>    https://lore.kernel.org/r/20260113210259.GA715789@bhelgaas/
>
> Can you include that URL for reference?


Sure thing, I'll resend with a Link: (I guess that's the appropriate 
method) after a few days.

Thanks,

Caleb


>
>> Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
>> Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
>
>> ---
>>   drivers/pci/probe.c | 6 ++++++
>>   1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index bccc7a4bdd79..4eacb741b4ec 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -395,6 +395,9 @@ static void pci_read_bridge_io(struct pci_dev *dev, struct resource *res,
>>   	unsigned long io_mask, io_granularity, base, limit;
>>   	struct pci_bus_region region;
>>   
>> +	if (!dev->io_window)
>> +		return;
>> +
>>   	io_mask = PCI_IO_RANGE_MASK;
>>   	io_granularity = 0x1000;
>>   	if (dev->io_window_1k) {
>> @@ -465,6 +468,9 @@ static void pci_read_bridge_mmio_pref(struct pci_dev *dev, struct resource *res,
>>   	pci_bus_addr_t base, limit;
>>   	struct pci_bus_region region;
>>   
>> +	if (!dev->pref_window)
>> +		return;
>> +
>>   	pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
>>   	pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
>>   	base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
>> -- 
>> 2.39.5
>>

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH 7/8] PCI: Skip bridge window reads when window is not supported
From: Bjorn Helgaas @ 2026-03-03 21:23 UTC (permalink / raw)
  To: Caleb James DeLisle
  Cc: linux-mips, naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel
In-Reply-To: <20260303190948.694783-8-cjd@cjdns.fr>

On Tue, Mar 03, 2026 at 07:09:47PM +0000, Caleb James DeLisle wrote:
> pci_read_bridge_io() and pci_read_bridge_mmio_pref() read bridge window
> registers unconditionally. If the registers are hardwired to zero
> (not implemented), both base and limit will be 0. Since (0 <= 0) is
> true, a bogus window [mem 0x00000000-0x000fffff] or [io 0x0000-0x0fff]
> gets created.
> 
> pci_read_bridge_windows() already detects unsupported windows by
> testing register writability and sets io_window/pref_window flags
> accordingly. Check these flags at the start of pci_read_bridge_io()
> and pci_read_bridge_mmio_pref() to skip reading registers when the
> window is not supported.
> 
> Suggested-by: Bjorn Helgaas <helgaas@kernel.org>

I think this refers to the conversation at:

  https://lore.kernel.org/r/20260113210259.GA715789@bhelgaas/

Can you include that URL for reference?

> Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
> Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

> ---
>  drivers/pci/probe.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index bccc7a4bdd79..4eacb741b4ec 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -395,6 +395,9 @@ static void pci_read_bridge_io(struct pci_dev *dev, struct resource *res,
>  	unsigned long io_mask, io_granularity, base, limit;
>  	struct pci_bus_region region;
>  
> +	if (!dev->io_window)
> +		return;
> +
>  	io_mask = PCI_IO_RANGE_MASK;
>  	io_granularity = 0x1000;
>  	if (dev->io_window_1k) {
> @@ -465,6 +468,9 @@ static void pci_read_bridge_mmio_pref(struct pci_dev *dev, struct resource *res,
>  	pci_bus_addr_t base, limit;
>  	struct pci_bus_region region;
>  
> +	if (!dev->pref_window)
> +		return;
> +
>  	pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
>  	pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
>  	base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
> -- 
> 2.39.5
> 

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* [PATCH 8/8] mips: dts: Add PCIe to EcoNet EN751221
From: Caleb James DeLisle @ 2026-03-03 19:09 UTC (permalink / raw)
  To: linux-mips
  Cc: naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt, cjd,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel
In-Reply-To: <20260303190948.694783-1-cjd@cjdns.fr>

Add PCIe based on EN7528 PCIe driver, also add two MT76 wifi devices
to SmartFiber XP8421-B.

Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
 arch/mips/boot/dts/econet/en751221.dtsi       | 114 ++++++++++++++++++
 .../econet/en751221_smartfiber_xp8421-b.dts   |  21 ++++
 arch/mips/econet/Kconfig                      |   2 +
 3 files changed, 137 insertions(+)

diff --git a/arch/mips/boot/dts/econet/en751221.dtsi b/arch/mips/boot/dts/econet/en751221.dtsi
index 2abeef5b744a..5568486ad8b5 100644
--- a/arch/mips/boot/dts/econet/en751221.dtsi
+++ b/arch/mips/boot/dts/econet/en751221.dtsi
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 /dts-v1/;
 
+#include <dt-bindings/clock/econet,en751221-scu.h>
+
 / {
 	compatible = "econet,en751221";
 	#address-cells = <1>;
@@ -30,6 +32,30 @@ cpuintc: interrupt-controller {
 		#interrupt-cells = <1>;
 	};
 
+	chip_scu: syscon@1fa20000 {
+		compatible = "econet,en751221-chip-scu", "syscon";
+		reg = <0x1fa20000 0x388>;
+	};
+
+	pcie_phy1: pcie-phy@1fac0000 {
+		compatible = "econet,en751221-pcie-phy1";
+		reg = <0x1fac0000 0x1000>;
+		#phy-cells = <0>;
+	};
+
+	pcie_phy0: pcie-phy@1faf2000 {
+		compatible = "econet,en751221-pcie-phy0";
+		reg = <0x1faf2000 0x1000>;
+		#phy-cells = <0>;
+	};
+
+	scuclk: clock-controller@1fb00000 {
+		compatible = "econet,en751221-scu", "syscon";
+		reg = <0x1fb00000 0x970>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
 	intc: interrupt-controller@1fb40000 {
 		compatible = "econet,en751221-intc";
 		reg = <0x1fb40000 0x100>;
@@ -41,6 +67,94 @@ intc: interrupt-controller@1fb40000 {
 		econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>;
 	};
 
+	pciecfg: pciecfg@1fb80000 {
+		compatible = "mediatek,generic-pciecfg", "syscon";
+		reg = <0x1fb80000 0x1000>;
+	};
+
+	pcie0: pcie@1fb81000 {
+		compatible = "econet,en7528-pcie";
+		device_type = "pci";
+		reg = <0x1fb81000 0x1000>;
+		reg-names = "port0";
+		linux,pci-domain = <0>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupt-parent = <&intc>;
+		interrupts = <23>;
+		interrupt-names = "pcie_irq";
+		clocks = <&scuclk EN751221_CLK_PCIE>;
+		clock-names = "sys_ck0";
+		phys = <&pcie_phy0>;
+		phy-names = "pcie-phy0";
+		bus-range = <0x00 0xff>;
+		ranges = <0x01000000 0 0x00000000 0x1f600000 0 0x00008000>,
+			 <0x82000000 0 0x20000000 0x20000000 0 0x08000000>;
+		status = "disabled";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+				<0 0 0 2 &pcie_intc0 1>,
+				<0 0 0 3 &pcie_intc0 2>,
+				<0 0 0 4 &pcie_intc0 3>;
+
+		pcie_intc0: interrupt-controller {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+		};
+
+		slot0: pcie@0,0 {
+			reg = <0x0000 0 0 0 0>;
+			device_type = "pci";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+		};
+	};
+
+	pcie1: pcie@1fb83000 {
+		compatible = "econet,en7528-pcie";
+		device_type = "pci";
+		reg = <0x1fb83000 0x1000>;
+		reg-names = "port1";
+		linux,pci-domain = <1>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupt-parent = <&intc>;
+		interrupts = <24>;
+		interrupt-names = "pcie_irq";
+		clocks = <&scuclk EN751221_CLK_PCIE>;
+		clock-names = "sys_ck1";
+		phys = <&pcie_phy1>;
+		phy-names = "pcie-phy1";
+		bus-range = <0x00 0xff>;
+		ranges = <0x81000000 0 0x00000000 0x1f608000 0 0x00008000>,
+			 <0x82000000 0 0x28000000 0x28000000 0 0x08000000>;
+		status = "disabled";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+				<0 0 0 2 &pcie_intc1 1>,
+				<0 0 0 3 &pcie_intc1 2>,
+				<0 0 0 4 &pcie_intc1 3>;
+
+		pcie_intc1: interrupt-controller {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+		};
+
+		slot1: pcie@1,0 {
+			reg = <0x0800 0 0 0 0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+		};
+	};
+
 	uart: serial@1fbf0000 {
 		compatible = "ns16550";
 		reg = <0x1fbf0000 0x30>;
diff --git a/arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts b/arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts
index 8223c5bce67f..c633bf73add6 100644
--- a/arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts
+++ b/arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts
@@ -17,3 +17,24 @@ chosen {
 		linux,usable-memory-range = <0x00020000 0x1bfe0000>;
 	};
 };
+
+&pcie0 {
+	status = "okay";
+};
+&slot0 {
+	wifi@0,0 {
+		/* MT7612E */
+		compatible = "mediatek,mt76";
+		reg = <0x0000 0 0 0 0>;
+	};
+};
+&pcie1 {
+	status = "okay";
+};
+&slot1 {
+	wifi@0,0 {
+		/* MT7592 */
+		compatible = "mediatek,mt76";
+		reg = <0x0000 0 0 0 0>;
+	};
+};
diff --git a/arch/mips/econet/Kconfig b/arch/mips/econet/Kconfig
index fd69884cc9a8..b37b9d25d5a4 100644
--- a/arch/mips/econet/Kconfig
+++ b/arch/mips/econet/Kconfig
@@ -13,7 +13,9 @@ choice
 		bool "EN751221 family"
 		select COMMON_CLK
 		select ECONET_EN751221_INTC
+		select HAVE_PCI
 		select IRQ_MIPS_CPU
+		select PCI_DRIVERS_GENERIC
 		select SMP
 		select SMP_UP
 		select SYS_SUPPORTS_SMP
-- 
2.39.5


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH 7/8] PCI: Skip bridge window reads when window is not supported
From: Caleb James DeLisle @ 2026-03-03 19:09 UTC (permalink / raw)
  To: linux-mips
  Cc: naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt, cjd,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel, Bjorn Helgaas
In-Reply-To: <20260303190948.694783-1-cjd@cjdns.fr>

pci_read_bridge_io() and pci_read_bridge_mmio_pref() read bridge window
registers unconditionally. If the registers are hardwired to zero
(not implemented), both base and limit will be 0. Since (0 <= 0) is
true, a bogus window [mem 0x00000000-0x000fffff] or [io 0x0000-0x0fff]
gets created.

pci_read_bridge_windows() already detects unsupported windows by
testing register writability and sets io_window/pref_window flags
accordingly. Check these flags at the start of pci_read_bridge_io()
and pci_read_bridge_mmio_pref() to skip reading registers when the
window is not supported.

Suggested-by: Bjorn Helgaas <helgaas@kernel.org>
Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
 drivers/pci/probe.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bccc7a4bdd79..4eacb741b4ec 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -395,6 +395,9 @@ static void pci_read_bridge_io(struct pci_dev *dev, struct resource *res,
 	unsigned long io_mask, io_granularity, base, limit;
 	struct pci_bus_region region;
 
+	if (!dev->io_window)
+		return;
+
 	io_mask = PCI_IO_RANGE_MASK;
 	io_granularity = 0x1000;
 	if (dev->io_window_1k) {
@@ -465,6 +468,9 @@ static void pci_read_bridge_mmio_pref(struct pci_dev *dev, struct resource *res,
 	pci_bus_addr_t base, limit;
 	struct pci_bus_region region;
 
+	if (!dev->pref_window)
+		return;
+
 	pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
 	pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
 	base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
-- 
2.39.5


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH 6/8] PCI: mediatek: Add support for EcoNet EN7528 SoC
From: Caleb James DeLisle @ 2026-03-03 19:09 UTC (permalink / raw)
  To: linux-mips
  Cc: naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt, cjd,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel
In-Reply-To: <20260303190948.694783-1-cjd@cjdns.fr>

Add support for the PCIe present on the EcoNet EN7528 (and EN751221) SoCs.

These SoCs have a mix of Gen1 and Gen2 capable ports, but the Gen2 ports
require re-training after startup.

Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
[cjd@cjdns.fr: Trivial change, reorder of_device_id alphabetical]
Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
 drivers/pci/controller/Kconfig         |   2 +-
 drivers/pci/controller/pcie-mediatek.c | 107 +++++++++++++++++++++++++
 2 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index 5aaed8ac6e44..f6a5fcacb38d 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -209,7 +209,7 @@ config PCI_MVEBU
 
 config PCIE_MEDIATEK
 	tristate "MediaTek PCIe controller"
-	depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST
+	depends on ARCH_AIROHA || ARCH_MEDIATEK || ECONET || COMPILE_TEST
 	depends on OF
 	depends on PCI_MSI
 	select IRQ_MSI_LIB
diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
index 5defa5cc4c2b..742edd05ee2b 100644
--- a/drivers/pci/controller/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
@@ -77,6 +77,7 @@
 
 #define PCIE_CONF_VEND_ID	0x100
 #define PCIE_CONF_DEVICE_ID	0x102
+#define PCIE_CONF_REV_CLASS	0x104
 #define PCIE_CONF_CLASS_ID	0x106
 
 #define PCIE_INT_MASK		0x420
@@ -89,6 +90,11 @@
 #define MSI_MASK		BIT(23)
 #define MTK_MSI_IRQS_NUM	32
 
+#define EN7528_HOST_MODE	0x00804201
+#define EN7528_LINKUP_REG	0x50
+#define EN7528_RC0_LINKUP	BIT(1)
+#define EN7528_RC1_LINKUP	BIT(2)
+
 #define PCIE_AHB_TRANS_BASE0_L	0x438
 #define PCIE_AHB_TRANS_BASE0_H	0x43c
 #define AHB2PCIE_SIZE(x)	((x) & GENMASK(4, 0))
@@ -753,6 +759,86 @@ static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port)
 	return 0;
 }
 
+static int mtk_pcie_startup_port_en7528(struct mtk_pcie_port *port)
+{
+	struct mtk_pcie *pcie = port->pcie;
+	struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
+	struct resource *mem = NULL;
+	struct resource_entry *entry;
+	u32 val, link_mask;
+	int err;
+
+	entry = resource_list_first_type(&host->windows, IORESOURCE_MEM);
+	if (entry)
+		mem = entry->res;
+	if (!mem)
+		return -EINVAL;
+
+	if (!pcie->cfg) {
+		dev_err(pcie->dev, "EN7528: pciecfg syscon not available\n");
+		return -EINVAL;
+	}
+
+	/* Assert all reset signals */
+	writel(0, port->base + PCIE_RST_CTRL);
+
+	/*
+	 * Enable PCIe link down reset, if link status changed from link up to
+	 * link down, this will reset MAC control registers and configuration
+	 * space.
+	 */
+	writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
+
+	/*
+	 * Described in PCIe CEM specification sections 2.2 (PERST# Signal) and
+	 * 2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST#
+	 * should be delayed 100ms (TPVPERL) for the power and clock to become
+	 * stable.
+	 */
+	msleep(100);
+
+	/* De-assert PHY, PE, PIPE, MAC and configuration reset */
+	val = readl(port->base + PCIE_RST_CTRL);
+	val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
+	       PCIE_MAC_SRSTB | PCIE_CRSTB;
+	writel(val, port->base + PCIE_RST_CTRL);
+
+	writel(PCIE_CLASS_CODE | PCIE_REVISION_ID,
+	       port->base + PCIE_CONF_REV_CLASS);
+	writel(EN7528_HOST_MODE, port->base);
+
+	link_mask = (port->slot == 0) ? EN7528_RC0_LINKUP : EN7528_RC1_LINKUP;
+
+	/* 100ms timeout value should be enough for Gen1/2 training */
+	err = regmap_read_poll_timeout(pcie->cfg, EN7528_LINKUP_REG, val,
+				       !!(val & link_mask), 20,
+				       100 * USEC_PER_MSEC);
+	if (err) {
+		dev_err(pcie->dev, "EN7528: port%d link timeout\n", port->slot);
+		return -ETIMEDOUT;
+	}
+
+	/* Set INTx mask */
+	val = readl(port->base + PCIE_INT_MASK);
+	val &= ~INTX_MASK;
+	writel(val, port->base + PCIE_INT_MASK);
+
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		mtk_pcie_enable_msi(port);
+
+	/* Set AHB to PCIe translation windows */
+	val = lower_32_bits(mem->start) |
+	      AHB2PCIE_SIZE(fls(resource_size(mem)));
+	writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
+
+	val = upper_32_bits(mem->start);
+	writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
+
+	writel(WIN_ENABLE, port->base + PCIE_AXI_WINDOW0);
+
+	return 0;
+}
+
 static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
 				      unsigned int devfn, int where)
 {
@@ -1149,6 +1235,20 @@ static int mtk_pcie_probe(struct platform_device *pdev)
 	if (err)
 		goto put_resources;
 
+	/* Retrain Gen1 links to reach Gen2 where supported */
+	if (pcie->soc->startup == mtk_pcie_startup_port_en7528) {
+		struct pci_bus *bus = host->bus;
+		struct pci_dev *rc = NULL;
+
+		while ((rc = pci_get_class(PCI_CLASS_BRIDGE_PCI << 8, rc))) {
+			if (rc->bus != bus)
+				continue;
+			if (!pcie_retrain_link(rc, true))
+				dev_info(dev, "port%d link retrained\n",
+					 PCI_SLOT(rc->devfn));
+		}
+	}
+
 	return 0;
 
 put_resources:
@@ -1264,8 +1364,15 @@ static const struct mtk_pcie_soc mtk_pcie_soc_mt7629 = {
 	.quirks = MTK_PCIE_FIX_CLASS_ID | MTK_PCIE_FIX_DEVICE_ID,
 };
 
+static const struct mtk_pcie_soc mtk_pcie_soc_en7528 = {
+	.ops = &mtk_pcie_ops_v2,
+	.startup = mtk_pcie_startup_port_en7528,
+	.setup_irq = mtk_pcie_setup_irq,
+};
+
 static const struct of_device_id mtk_pcie_ids[] = {
 	{ .compatible = "airoha,an7583-pcie", .data = &mtk_pcie_soc_an7583 },
+	{ .compatible = "econet,en7528-pcie", .data = &mtk_pcie_soc_en7528 },
 	{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
 	{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
 	{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_mt2712 },
-- 
2.39.5


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH 5/8] dt-bindings: PCI: mediatek: Add support for EcoNet EN7528
From: Caleb James DeLisle @ 2026-03-03 19:09 UTC (permalink / raw)
  To: linux-mips
  Cc: naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt, cjd,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel
In-Reply-To: <20260303190948.694783-1-cjd@cjdns.fr>

Introduce EcoNet EN7528 SoC compatible in MediaTek PCIe controller
binding.

EcoNet PCIe controller has the same configuration model as
Mediatek v2 but is initiallized more similarly to an MT7621
PCIe.

Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
 Documentation/devicetree/bindings/pci/mediatek-pcie.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.yaml b/Documentation/devicetree/bindings/pci/mediatek-pcie.yaml
index 0b8c78ec4f91..57cbfbff7a31 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.yaml
@@ -14,6 +14,7 @@ properties:
     oneOf:
       - enum:
           - airoha,an7583-pcie
+          - econet,en7528-pcie
           - mediatek,mt2712-pcie
           - mediatek,mt7622-pcie
           - mediatek,mt7629-pcie
-- 
2.39.5


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH 4/8] phy: econet: Add PCIe PHY driver for EcoNet EN751221 and EN7528 SoCs.
From: Caleb James DeLisle @ 2026-03-03 19:09 UTC (permalink / raw)
  To: linux-mips
  Cc: naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt, cjd,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel
In-Reply-To: <20260303190948.694783-1-cjd@cjdns.fr>

Introduce support for EcoNet PCIe PHY controllers found in EN751221
and EN7528 SoCs, these SoCs are not identical but are similar, each
having one Gen1 port, and one Gen1/Gen2 port.

Co-developed-by: Ahmed Naseef <naseefkm@gmail.com>
Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
[cjd@cjdns.fr: add EN751221 support and refactor for clarity]
Co-developed-by: Caleb James DeLisle <cjd@cjdns.fr>
Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
 MAINTAINERS                   |   1 +
 drivers/phy/Kconfig           |  12 +++
 drivers/phy/Makefile          |   1 +
 drivers/phy/phy-econet-pcie.c | 180 ++++++++++++++++++++++++++++++++++
 4 files changed, 194 insertions(+)
 create mode 100644 drivers/phy/phy-econet-pcie.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ae053b1f174f..5d4544590069 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9128,6 +9128,7 @@ M:	Caleb James DeLisle <cjd@cjdns.fr>
 L:	linux-mips@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml
+F:	drivers/phy/phy-econet-pcie.c
 
 ECRYPT FILE SYSTEM
 M:	Tyler Hicks <code@tyhicks.com>
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 02467dfd4fb0..60efc37f6eb0 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -123,6 +123,18 @@ config PHY_AIROHA_PCIE
 	  This driver create the basic PHY instance and provides initialize
 	  callback for PCIe GEN3 port.
 
+config PHY_ECONET_PCIE
+	tristate "EcoNet PCIe-PHY Driver"
+	depends on ECONET || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	select REGMAP_MMIO
+	help
+	  Say Y here to add support for EcoNet PCIe PHY driver.
+	  This driver create the basic PHY instance and provides initialize
+	  callback for PCIe GEN1 and GEN2 ports. This PHY is found on
+	  EcoNet SoCs including EN751221 and EN7528.
+
 config PHY_NXP_PTN3222
 	tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
 	depends on I2C
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index a648c2e02a83..a77f182ee8f3 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -15,6 +15,7 @@ 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_ECONET_PCIE)		+= phy-econet-pcie.o
 obj-$(CONFIG_PHY_NXP_PTN3222)		+= phy-nxp-ptn3222.o
 obj-$(CONFIG_PHY_SPACEMIT_K1_PCIE)	+= phy-spacemit-k1-pcie.o
 obj-$(CONFIG_GENERIC_PHY)		+= allwinner/	\
diff --git a/drivers/phy/phy-econet-pcie.c b/drivers/phy/phy-econet-pcie.c
new file mode 100644
index 000000000000..f9d6d061f54a
--- /dev/null
+++ b/drivers/phy/phy-econet-pcie.c
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Author: Caleb James DeLisle <cjd@cjdns.fr>
+ *	   Ahmed Naseef <naseefkm@gmail.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* Rx detection timing for EN751221: 16*8 clock cycles  */
+#define EN751221_RXDET_VAL		16
+
+/* Rx detection timing when in power mode 3 */
+#define EN75_RXDET_P3_REG		0xa28
+#define EN75_RXDET_P3_MASK		GENMASK(17, 9)
+
+/* Rx detection timing when in power mode 2 */
+#define EN75_RXDET_P2_REG		0xa2c
+#define EN75_RXDET_P2_MASK		GENMASK(8, 0)
+
+/* Rx impedance */
+#define EN75_RX_IMPEDANCE_REG		0xb2c
+#define EN75_RX_IMPEDANCE_MASK		GENMASK(13, 12)
+enum en75_rx_impedance {
+	EN75_RX_IMPEDANCE_100_OHM	= 0,
+	EN75_RX_IMPEDANCE_95_OHM	= 1,
+	EN75_RX_IMPEDANCE_90_OHM	= 2,
+};
+
+/* PLL Invert clock */
+#define EN75_PLL_PH_INV_REG		0x4a0
+#define EN75_PLL_PH_INV_MASK		BIT(5)
+
+struct en75_phy_op {
+	u32 reg;
+	u32 mask;
+	u32 val;
+};
+
+struct en7528_pcie_phy {
+	struct regmap *regmap;
+	const struct en75_phy_op *data;
+};
+
+/* Port 0 PHY: set LCDDS_CLK_PH_INV for PLL operation */
+static const struct en75_phy_op en7528_phy_port0[] = {
+	{
+		.reg = EN75_PLL_PH_INV_REG,
+		.mask = EN75_PLL_PH_INV_MASK,
+		.val = 1,
+	},
+	{ /* sentinel */ }
+};
+
+/* EN7528 Port 1 PHY: Rx impedance tuning, target R -5 Ohm */
+static const struct en75_phy_op en7528_phy_port1[] = {
+	{
+		.reg = EN75_RX_IMPEDANCE_REG,
+		.mask = EN75_RX_IMPEDANCE_MASK,
+		.val = EN75_RX_IMPEDANCE_95_OHM,
+	},
+	{ /* sentinel */ }
+};
+
+/* EN751221 Port 1 PHY, set RX detect to 16*8 clock cycles */
+static const struct en75_phy_op en751221_phy_port1[] = {
+	{
+		.reg = EN75_RXDET_P3_REG,
+		.mask = EN75_RXDET_P3_MASK,
+		.val = EN751221_RXDET_VAL,
+	},
+	{
+		.reg = EN75_RXDET_P2_REG,
+		.mask = EN75_RXDET_P2_MASK,
+		.val = EN751221_RXDET_VAL,
+	},
+	{ /* sentinel */ }
+};
+
+static int en75_pcie_phy_init(struct phy *phy)
+{
+	struct en7528_pcie_phy *ephy = phy_get_drvdata(phy);
+	const struct en75_phy_op *data = ephy->data;
+	int i, ret;
+	u32 val;
+
+	for (i = 0; data[i].mask || data[i].val; i++) {
+		if (i)
+			usleep_range(1000, 2000);
+
+		val = field_prep(data[i].mask, data[i].val);
+
+		ret = regmap_update_bits(ephy->regmap, data[i].reg,
+					 data[i].mask, val);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct phy_ops en75_pcie_phy_ops = {
+	.init	= en75_pcie_phy_init,
+	.owner	= THIS_MODULE,
+};
+
+static int en75_pcie_phy_probe(struct platform_device *pdev)
+{
+	struct regmap_config regmap_config = {
+		.reg_bits = 32,
+		.val_bits = 32,
+		.reg_stride = 4,
+	};
+	struct device *dev = &pdev->dev;
+	const struct en75_phy_op *data;
+	struct phy_provider *provider;
+	struct en7528_pcie_phy *ephy;
+	void __iomem *base;
+	struct phy *phy;
+	int i;
+
+	data = of_device_get_match_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	ephy = devm_kzalloc(dev, sizeof(*ephy), GFP_KERNEL);
+	if (!ephy)
+		return -ENOMEM;
+
+	ephy->data = data;
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	/* Set max_register to highest used register */
+	for (i = 0; data[i].mask || data[i].val; i++)
+		if (data[i].reg > regmap_config.max_register)
+			regmap_config.max_register = data[i].reg;
+
+	ephy->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+	if (IS_ERR(ephy->regmap))
+		return PTR_ERR(ephy->regmap);
+
+	phy = devm_phy_create(dev, dev->of_node, &en75_pcie_phy_ops);
+	if (IS_ERR(phy))
+		return PTR_ERR(phy);
+
+	phy_set_drvdata(phy, ephy);
+
+	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+	return PTR_ERR_OR_ZERO(provider);
+}
+
+static const struct of_device_id en75_pcie_phy_ids[] = {
+	{ .compatible = "econet,en7528-pcie-phy0", .data = en7528_phy_port0 },
+	{ .compatible = "econet,en7528-pcie-phy1", .data = en7528_phy_port1 },
+	{ .compatible = "econet,en751221-pcie-phy0", .data = en7528_phy_port0 },
+	{ .compatible = "econet,en751221-pcie-phy1", .data = en751221_phy_port1 },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, en75_pcie_phy_ids);
+
+static struct platform_driver en75_pcie_phy_driver = {
+	.probe = en75_pcie_phy_probe,
+	.driver = {
+		.name = "econet-pcie-phy",
+		.of_match_table = en75_pcie_phy_ids,
+	},
+};
+module_platform_driver(en75_pcie_phy_driver);
+
+MODULE_AUTHOR("Caleb James DeLisle <cjd@cjdns.fr>");
+MODULE_DESCRIPTION("EcoNet PCIe PHY driver");
+MODULE_LICENSE("GPL");
-- 
2.39.5


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528
From: Caleb James DeLisle @ 2026-03-03 19:09 UTC (permalink / raw)
  To: linux-mips
  Cc: naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt, cjd,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel
In-Reply-To: <20260303190948.694783-1-cjd@cjdns.fr>

EN751221 and EN7528 SoCs have two PCIe slots, and each one has a
PHY which behaves slightly differently because one slot is Gen1/Gen2
while the other is Gen1 only.

Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
 .../phy/econet,en751221-pcie-phy.yaml         | 57 +++++++++++++++++++
 MAINTAINERS                                   |  6 ++
 2 files changed, 63 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml

diff --git a/Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml
new file mode 100644
index 000000000000..8e1d3c791c6e
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/econet,en751221-pcie-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: EcoNet PCI-Express PHY for EcoNet EN751221 and EN7528
+
+maintainers:
+  - Caleb James DeLisle <cjd@cjdns.fr>
+
+description:
+  The PCIe PHY supports physical layer functionality for PCIe Gen1 and
+  Gen1/Gen2 ports. On these SoCs, port 0 is a Gen1-only port while
+  port 1 is Gen1/Gen2 capable.
+
+properties:
+  compatible:
+    enum:
+      - econet,en751221-pcie-phy0
+      - econet,en751221-pcie-phy1
+      - econet,en7528-pcie-phy0
+      - econet,en7528-pcie-phy1
+
+  reg:
+    maxItems: 1
+
+  "#phy-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/phy/phy.h>
+    soc {
+      #address-cells = <1>;
+      #size-cells = <1>;
+
+      pcie_phy0: pcie-phy@1faf2000 {
+        compatible = "econet,en7528-pcie-phy0";
+        reg = <0x1faf2000 0x1000>;
+        #phy-cells = <0>;
+      };
+
+      pcie_phy1: pcie-phy@1fac0000 {
+        compatible = "econet,en7528-pcie-phy1";
+        reg = <0x1fac0000 0x1000>;
+        #phy-cells = <0>;
+      };
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 56cf73ce91b8..ae053b1f174f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9123,6 +9123,12 @@ F:	drivers/irqchip/irq-econet-en751221.c
 F:	include/dt-bindings/clock/econet,en751221-scu.h
 F:	include/dt-bindings/reset/econet,en751221-scu.h
 
+ECONET PCIE PHY DRIVER
+M:	Caleb James DeLisle <cjd@cjdns.fr>
+L:	linux-mips@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml
+
 ECRYPT FILE SYSTEM
 M:	Tyler Hicks <code@tyhicks.com>
 L:	ecryptfs@vger.kernel.org
-- 
2.39.5


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH 2/8] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu
From: Caleb James DeLisle @ 2026-03-03 19:09 UTC (permalink / raw)
  To: linux-mips
  Cc: naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt, cjd,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel
In-Reply-To: <20260303190948.694783-1-cjd@cjdns.fr>

EcoNet EN751221 clock/reset driver is significantly similar to the
EN7523 / EN7581, however the EN751221 does not have a neat batch of clock
divider registers so there are fewer known clocks, and the frequency of
each clock is derived differently. This clock driver will probably work
correctly on EN751627, EN7528, and EN7580.

Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
 drivers/clk/Kconfig      |   6 +-
 drivers/clk/clk-en7523.c | 236 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 234 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 3d803b4cf5c1..47df6073a72b 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -218,13 +218,13 @@ config COMMON_CLK_CS2000_CP
 	  If you say yes here you get support for the CS2000 clock multiplier.
 
 config COMMON_CLK_EN7523
-	bool "Clock driver for Airoha EN7523 SoC system clocks"
+	bool "Clock driver for Airoha/EcoNet SoC system clocks"
 	depends on OF
-	depends on ARCH_AIROHA || COMPILE_TEST
+	depends on ARCH_AIROHA || ECONET || COMPILE_TEST
 	default ARCH_AIROHA
 	help
 	  This driver provides the fixed clocks and gates present on Airoha
-	  ARM silicon.
+	  and EcoNet silicon.
 
 config COMMON_CLK_EP93XX
 	tristate "Clock driver for Cirrus Logic ep93xx SoC"
diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 08cc8e5acf43..b31e6d3c91a2 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
@@ -11,6 +12,8 @@
 #include <dt-bindings/clock/en7523-clk.h>
 #include <dt-bindings/reset/airoha,en7523-reset.h>
 #include <dt-bindings/reset/airoha,en7581-reset.h>
+#include <dt-bindings/clock/econet,en751221-scu.h>
+#include <dt-bindings/reset/econet,en751221-scu.h>
 
 #define RST_NR_PER_BANK			32
 
@@ -33,15 +36,47 @@
 #define   REG_RESET_CONTROL_PCIEHB	BIT(29)
 #define   REG_RESET_CONTROL_PCIE1	BIT(27)
 #define   REG_RESET_CONTROL_PCIE2	BIT(26)
+#define REG_HIR				0x064
+#define   REG_HIR_MASK			GENMASK(31, 16)
 /* EN7581 */
 #define REG_NP_SCU_PCIC			0x88
 #define REG_NP_SCU_SSTR			0x9c
 #define REG_PCIE_XSI0_SEL_MASK		GENMASK(14, 13)
 #define REG_PCIE_XSI1_SEL_MASK		GENMASK(12, 11)
 #define REG_CRYPTO_CLKSRC2		0x20c
+/* EN751221 */
+#define EN751221_REG_SPI_DIV		0x0cc
+#define EN751221_REG_SPI_DIV_MASK	GENMASK(31, 8)
+#define EN751221_SPI_BASE		500000000
+#define EN751221_SPI_BASE_EN7526C	400000000
+#define EN751221_REG_BUS		0x284
+#define EN751221_REG_BUS_MASK		GENMASK(21, 12)
+#define EN751221_REG_SSR3		0x094
+#define EN751221_REG_SSR3_GSW_MASK	GENMASK(9, 8)
 
 #define REG_RST_CTRL2			0x830
 #define REG_RST_CTRL1			0x834
+#define EN751221_REG_RST_DMT		0x84
+#define EN751221_REG_RST_USB		0xec
+
+enum en_hir {
+	HIR_UNKNOWN	= -1,
+	HIR_TC3169	= 0,
+	HIR_TC3182	= 1,
+	HIR_RT65168	= 2,
+	HIR_RT63165	= 3,
+	HIR_RT63365	= 4,
+	HIR_MT751020	= 5,
+	HIR_MT7505	= 6,
+	HIR_EN751221	= 7,
+	HIR_EN7526C	= 8,
+	HIR_EN751627	= 9,
+	HIR_EN7580	= 10,
+	HIR_EN7528	= 11,
+	HIR_EN7523	= 12,
+	HIR_EN7581	= 13,
+	HIR_MAX		= 14,
+};
 
 struct en_clk_desc {
 	int id;
@@ -93,6 +128,8 @@ static const u32 bus7581_base[] = { 600000000, 540000000 };
 static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
 static const u32 crypto_base[] = { 540000000, 480000000 };
 static const u32 emmc7581_base[] = { 200000000, 150000000 };
+/* EN751221 */
+static const u32 gsw751221_base[] = { 500000000, 250000000, 400000000, 200000000 };
 
 static const struct en_clk_desc en7523_base_clks[] = {
 	{
@@ -300,6 +337,13 @@ static const u16 en7581_rst_ofs[] = {
 	REG_RST_CTRL1,
 };
 
+static const u16 en751221_rst_ofs[] = {
+	REG_RST_CTRL2,
+	REG_RST_CTRL1,
+	EN751221_REG_RST_DMT,
+	EN751221_REG_RST_USB,
+};
+
 static const u16 en7523_rst_map[] = {
 	/* RST_CTRL2 */
 	[EN7523_XPON_PHY_RST]		= 0,
@@ -405,8 +449,61 @@ static const u16 en7581_rst_map[] = {
 	[EN7581_XPON_MAC_RST]		= RST_NR_PER_BANK + 31,
 };
 
+static const u16 en751221_rst_map[] = {
+	/* RST_CTRL2 */
+	[EN751221_XPON_PHY_RST]		= 0,
+	[EN751221_GFAST_RST]		= 1,
+	[EN751221_CPU_TIMER2_RST]	= 2,
+	[EN751221_UART3_RST]		= 3,
+	[EN751221_UART4_RST]		= 4,
+	[EN751221_UART5_RST]		= 5,
+	[EN751221_I2C2_RST]		= 6,
+	[EN751221_XSI_MAC_RST]		= 7,
+	[EN751221_XSI_PHY_RST]		= 8,
+
+	/* RST_CTRL1 */
+	[EN751221_PCM1_ZSI_ISI_RST]	= RST_NR_PER_BANK + 0,
+	[EN751221_FE_QDMA1_RST]		= RST_NR_PER_BANK + 1,
+	[EN751221_FE_QDMA2_RST]		= RST_NR_PER_BANK + 2,
+	[EN751221_FE_UNZIP_RST]		= RST_NR_PER_BANK + 3,
+	[EN751221_PCM2_RST]		= RST_NR_PER_BANK + 4,
+	[EN751221_PTM_MAC_RST]		= RST_NR_PER_BANK + 5,
+	[EN751221_CRYPTO_RST]		= RST_NR_PER_BANK + 6,
+	[EN751221_SAR_RST]		= RST_NR_PER_BANK + 7,
+	[EN751221_TIMER_RST]		= RST_NR_PER_BANK + 8,
+	[EN751221_INTC_RST]		= RST_NR_PER_BANK + 9,
+	[EN751221_BONDING_RST]		= RST_NR_PER_BANK + 10,
+	[EN751221_PCM1_RST]		= RST_NR_PER_BANK + 11,
+	[EN751221_UART_RST]		= RST_NR_PER_BANK + 12,
+	[EN751221_GPIO_RST]		= RST_NR_PER_BANK + 13,
+	[EN751221_GDMA_RST]		= RST_NR_PER_BANK + 14,
+	[EN751221_I2C_MASTER_RST]	= RST_NR_PER_BANK + 16,
+	[EN751221_PCM2_ZSI_ISI_RST]	= RST_NR_PER_BANK + 17,
+	[EN751221_SFC_RST]		= RST_NR_PER_BANK + 18,
+	[EN751221_UART2_RST]		= RST_NR_PER_BANK + 19,
+	[EN751221_GDMP_RST]		= RST_NR_PER_BANK + 20,
+	[EN751221_FE_RST]		= RST_NR_PER_BANK + 21,
+	[EN751221_USB_HOST_P0_RST]	= RST_NR_PER_BANK + 22,
+	[EN751221_GSW_RST]		= RST_NR_PER_BANK + 23,
+	[EN751221_SFC2_PCM_RST]		= RST_NR_PER_BANK + 25,
+	[EN751221_PCIE0_RST]		= RST_NR_PER_BANK + 26,
+	[EN751221_PCIE1_RST]		= RST_NR_PER_BANK + 27,
+	[EN751221_CPU_TIMER_RST]	= RST_NR_PER_BANK + 28,
+	[EN751221_PCIE_HB_RST]		= RST_NR_PER_BANK + 29,
+	[EN751221_SIMIF_RST]		= RST_NR_PER_BANK + 30,
+	[EN751221_XPON_MAC_RST]		= RST_NR_PER_BANK + 31,
+
+	/* RST_DMT */
+	[EN751221_DMT_RST]		= 2 * RST_NR_PER_BANK + 0,
+
+	/* RST_USB */
+	[EN751221_USB_PHY_P0_RST]	= 3 * RST_NR_PER_BANK + 6,
+	[EN751221_USB_PHY_P1_RST]	= 3 * RST_NR_PER_BANK + 7,
+};
+
 static int en7581_reset_register(struct device *dev, void __iomem *base,
-				 const u16 *rst_map, int nr_resets);
+				 const u16 *rst_map, int nr_resets,
+				 const u16 *rst_reg_ofs);
 
 static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
 {
@@ -604,7 +701,8 @@ static int en7523_clk_hw_init(struct platform_device *pdev,
 	en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
 
 	return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map,
-				     ARRAY_SIZE(en7523_rst_map));
+				     ARRAY_SIZE(en7523_rst_map),
+				     en7581_rst_ofs);
 }
 
 static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
@@ -705,7 +803,8 @@ static const struct reset_control_ops en7581_reset_ops = {
 };
 
 static int en7581_reset_register(struct device *dev, void __iomem *base,
-				 const u16 *rst_map, int nr_resets)
+				 const u16 *rst_map, int nr_resets,
+				 const u16 *rst_reg_ofs)
 {
 	struct en_rst_data *rst_data;
 
@@ -713,7 +812,7 @@ static int en7581_reset_register(struct device *dev, void __iomem *base,
 	if (!rst_data)
 		return -ENOMEM;
 
-	rst_data->bank_ofs = en7581_rst_ofs;
+	rst_data->bank_ofs = rst_reg_ofs;
 	rst_data->idx_map = rst_map;
 	rst_data->base = base;
 
@@ -752,7 +851,123 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
 	writel(val | 3, base + REG_NP_SCU_PCIC);
 
 	return en7581_reset_register(&pdev->dev, base, en7581_rst_map,
-				     ARRAY_SIZE(en7581_rst_map));
+				     ARRAY_SIZE(en7581_rst_map),
+				     en7581_rst_ofs);
+}
+
+static enum en_hir get_hw_id(void __iomem *np_base)
+{
+	u32 val = FIELD_GET(REG_HIR_MASK, readl(np_base + REG_HIR));
+
+	if (val < HIR_MAX)
+		return (enum en_hir) val;
+
+	return HIR_UNKNOWN;
+}
+
+static void en751221_try_register_clk(struct device *dev, int key,
+				      struct clk_hw_onecell_data *clk_data,
+				      const char *name, u32 rate)
+{
+	struct clk_hw *hw;
+
+	hw = clk_hw_register_fixed_rate(dev, name, NULL, 0, rate);
+	if (IS_ERR(hw))
+		pr_err("Failed to register clk %s: %pe\n", name, hw);
+	else
+		clk_data->hws[key] = hw;
+}
+
+static void en751221_register_clocks(struct device *dev,
+				     struct clk_hw_onecell_data *clk_data,
+				     struct regmap *map, void __iomem *np_base)
+{
+	enum en_hir hid = get_hw_id(np_base);
+	struct clk_hw *hw;
+	u32 rate;
+	u32 div;
+	int err;
+
+	/* PCI */
+	hw = en7523_register_pcie_clk(dev, np_base);
+	clk_data->hws[EN751221_CLK_PCIE] = hw;
+
+	/* SPI */
+	rate = EN751221_SPI_BASE;
+	if (hid == HIR_EN7526C)
+		rate = EN751221_SPI_BASE_EN7526C;
+
+	err = regmap_read(map, EN751221_REG_SPI_DIV, &div);
+	if (err) {
+		pr_err("Failed reading fixed clk div %s: %d\n",
+		       "spi", err);
+	} else {
+		div = FIELD_GET(EN751221_REG_SPI_DIV_MASK, div) * 2;
+		if (!div)
+			div = 40;
+
+		en751221_try_register_clk(dev, EN751221_CLK_SPI, clk_data,
+					  "spi", rate / div);
+	}
+
+	/* BUS */
+	rate = FIELD_GET(EN751221_REG_BUS_MASK,
+			 readl(np_base + EN751221_REG_BUS));
+	rate *= 1000000;
+	en751221_try_register_clk(dev, EN751221_CLK_BUS, clk_data, "bus",
+				  rate);
+
+	/* CPU */
+	en751221_try_register_clk(dev, EN751221_CLK_CPU, clk_data, "cpu",
+				  rate * 4);
+
+	/* HPT */
+	switch (hid) {
+	case HIR_EN751221:
+	case HIR_EN751627:
+	case HIR_EN7526C:
+	case HIR_EN7580:
+	case HIR_EN7528:
+		rate = 200000000;
+		break;
+	case HIR_MT7505:
+		rate = 100000000;
+		break;
+	case HIR_MT751020:
+		rate = 800000000 / 3;
+		break;
+	default:
+		rate = 250000000;
+	}
+	en751221_try_register_clk(dev, EN751221_CLK_HPT, clk_data, "hpt",
+				  rate);
+
+	/* GSW */
+	rate = FIELD_GET(EN751221_REG_SSR3_GSW_MASK,
+			 readl(np_base + EN751221_REG_SSR3));
+	en751221_try_register_clk(dev, EN751221_CLK_GSW, clk_data, "gsw",
+				  gsw751221_base[rate]);
+}
+
+static int en751221_clk_hw_init(struct platform_device *pdev,
+				struct clk_hw_onecell_data *clk_data)
+{
+	struct regmap *map;
+	void __iomem *base;
+
+	map = syscon_regmap_lookup_by_compatible("econet,en751221-chip-scu");
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	en751221_register_clocks(&pdev->dev, clk_data, map, base);
+
+	return en7581_reset_register(&pdev->dev, base, en751221_rst_map,
+				     ARRAY_SIZE(en751221_rst_map),
+				     en751221_rst_ofs);
 }
 
 static int en7523_clk_probe(struct platform_device *pdev)
@@ -799,9 +1014,20 @@ static const struct en_clk_soc_data en7581_data = {
 	.hw_init = en7581_clk_hw_init,
 };
 
+static const struct en_clk_soc_data en751221_data = {
+	.num_clocks = EN751221_MAX_CLKS,
+	.pcie_ops = {
+		.is_enabled = en7523_pci_is_enabled,
+		.prepare = en7523_pci_prepare,
+		.unprepare = en7523_pci_unprepare,
+	},
+	.hw_init = en751221_clk_hw_init,
+};
+
 static const struct of_device_id of_match_clk_en7523[] = {
 	{ .compatible = "airoha,en7523-scu", .data = &en7523_data },
 	{ .compatible = "airoha,en7581-scu", .data = &en7581_data },
+	{ .compatible = "econet,en751221-scu", .data = &en751221_data },
 	{ /* sentinel */ }
 };
 
-- 
2.39.5


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH 1/8] dt-bindings: clock, reset: Add econet EN751221 bindings
From: Caleb James DeLisle @ 2026-03-03 19:09 UTC (permalink / raw)
  To: linux-mips
  Cc: naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt, cjd,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel
In-Reply-To: <20260303190948.694783-1-cjd@cjdns.fr>

Add clock and reset bindings for EN751221 as well as
a "chip-scu" which is an additional regmap that is used
by the clock driver as well as others. This split of the
SCU across two register areas is the same as the Airoha
AN758x family.

Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
 .../bindings/clock/airoha,en7523-scu.yaml     | 19 ++++++-
 .../mips/econet,en751221-chip-scu.yaml        | 41 ++++++++++++++++
 MAINTAINERS                                   |  3 ++
 .../dt-bindings/clock/econet,en751221-scu.h   | 15 ++++++
 .../dt-bindings/reset/econet,en751221-scu.h   | 49 +++++++++++++++++++
 5 files changed, 126 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml
 create mode 100644 include/dt-bindings/clock/econet,en751221-scu.h
 create mode 100644 include/dt-bindings/reset/econet,en751221-scu.h

diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
index a8471367175b..e60e54273393 100644
--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
@@ -32,6 +32,7 @@ properties:
       - enum:
           - airoha,en7523-scu
           - airoha,en7581-scu
+          - econet,en751221-scu
 
   reg:
     items:
@@ -67,7 +68,10 @@ allOf:
   - if:
       properties:
         compatible:
-          const: airoha,en7581-scu
+          items:
+            - enum:
+                - airoha,en7581-scu
+                - econet,en751221-scu
     then:
       properties:
         reg:
@@ -98,3 +102,16 @@ examples:
               #reset-cells = <1>;
       };
     };
+
+  - |
+    soc {
+      #address-cells = <1>;
+      #size-cells = <1>;
+
+      scuclk2: clock-controller@1fb00000 {
+        compatible = "econet,en751221-scu";
+        reg = <0x1fb00000 0x970>;
+        #clock-cells = <1>;
+        #reset-cells = <1>;
+      };
+    };
diff --git a/Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml b/Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml
new file mode 100644
index 000000000000..7c7c8cf8d2a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mips/econet,en751221-chip-scu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: EcoNet Chip SCU Controller for EN751221 SoC
+
+maintainers:
+  - Caleb James DeLisle <cjd@cjdns.fr>
+
+description:
+  The EcoNet chip-scu block provides a configuration interface for clock,
+  io-muxing and other functionalities used by multiple controllers (e.g. clock,
+  pinctrl, ecc) on EN751221 SoC.
+
+properties:
+  compatible:
+    items:
+      - const: econet,en751221-chip-scu
+      - const: syscon
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    soc {
+      #address-cells = <1>;
+      #size-cells = <1>;
+      syscon@1fa20000 {
+        compatible = "econet,en751221-chip-scu", "syscon";
+        reg = <0x1fa20000 0x388>;
+      };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 14899f1de77e..56cf73ce91b8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9113,12 +9113,15 @@ M:	Caleb James DeLisle <cjd@cjdns.fr>
 L:	linux-mips@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml
+F:	Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml
 F:	Documentation/devicetree/bindings/mips/econet.yaml
 F:	Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml
 F:	arch/mips/boot/dts/econet/
 F:	arch/mips/econet/
 F:	drivers/clocksource/timer-econet-en751221.c
 F:	drivers/irqchip/irq-econet-en751221.c
+F:	include/dt-bindings/clock/econet,en751221-scu.h
+F:	include/dt-bindings/reset/econet,en751221-scu.h
 
 ECRYPT FILE SYSTEM
 M:	Tyler Hicks <code@tyhicks.com>
diff --git a/include/dt-bindings/clock/econet,en751221-scu.h b/include/dt-bindings/clock/econet,en751221-scu.h
new file mode 100644
index 000000000000..34179b8fe2f9
--- /dev/null
+++ b/include/dt-bindings/clock/econet,en751221-scu.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_
+#define _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_
+
+#define EN751221_CLK_PCIE	0
+#define EN751221_CLK_SPI	1
+#define EN751221_CLK_BUS	2
+#define EN751221_CLK_CPU	3
+#define EN751221_CLK_HPT	4
+#define EN751221_CLK_GSW	5
+
+#define EN751221_MAX_CLKS	6
+
+#endif /* _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ */
diff --git a/include/dt-bindings/reset/econet,en751221-scu.h b/include/dt-bindings/reset/econet,en751221-scu.h
new file mode 100644
index 000000000000..bad499d4d50a
--- /dev/null
+++ b/include/dt-bindings/reset/econet,en751221-scu.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef __DT_BINDINGS_RESET_CONTROLLER_ECONET_EN751221_H_
+#define __DT_BINDINGS_RESET_CONTROLLER_ECONET_EN751221_H_
+
+#define EN751221_XPON_PHY_RST		 0
+#define EN751221_PCM1_ZSI_ISI_RST	 1
+#define EN751221_FE_QDMA1_RST		 2
+#define EN751221_FE_QDMA2_RST		 3
+#define EN751221_FE_UNZIP_RST		 4
+#define EN751221_PCM2_RST		 5
+#define EN751221_PTM_MAC_RST		 6
+#define EN751221_CRYPTO_RST		 7
+#define EN751221_SAR_RST		 8
+#define EN751221_TIMER_RST		 9
+#define EN751221_INTC_RST		10
+#define EN751221_BONDING_RST		11
+#define EN751221_PCM1_RST		12
+#define EN751221_UART_RST		13
+#define EN751221_GPIO_RST		14
+#define EN751221_GDMA_RST		15
+#define EN751221_I2C_MASTER_RST		16
+#define EN751221_PCM2_ZSI_ISI_RST	17
+#define EN751221_SFC_RST		18
+#define EN751221_UART2_RST		19
+#define EN751221_GDMP_RST		20
+#define EN751221_FE_RST			21
+#define EN751221_USB_HOST_P0_RST	22
+#define EN751221_GSW_RST		23
+#define EN751221_SFC2_PCM_RST		24
+#define EN751221_PCIE0_RST		25
+#define EN751221_PCIE1_RST		26
+#define EN751221_CPU_TIMER_RST		27
+#define EN751221_PCIE_HB_RST		28
+#define EN751221_SIMIF_RST		29
+#define EN751221_XPON_MAC_RST		30
+#define EN751221_GFAST_RST		31
+#define EN751221_CPU_TIMER2_RST		32
+#define EN751221_UART3_RST		33
+#define EN751221_UART4_RST		34
+#define EN751221_UART5_RST		35
+#define EN751221_I2C2_RST		36
+#define EN751221_XSI_MAC_RST		37
+#define EN751221_XSI_PHY_RST		38
+#define EN751221_DMT_RST		39
+#define EN751221_USB_PHY_P0_RST		40
+#define EN751221_USB_PHY_P1_RST		41
+
+#endif /* __DT_BINDINGS_RESET_CONTROLLER_ECONET_EN751221_H_ */
-- 
2.39.5


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH 0/8] mips: econet: Add clk/reset and PCIe support
From: Caleb James DeLisle @ 2026-03-03 19:09 UTC (permalink / raw)
  To: linux-mips
  Cc: naseefkm, mturquette, sboyd, robh, krzk+dt, conor+dt, cjd,
	tsbogend, ryder.lee, jianjun.wang, lpieralisi, kwilczynski, mani,
	bhelgaas, vkoul, neil.armstrong, p.zabel, matthias.bgg,
	angelogioacchino.delregno, nbd, ansuelsmth, linux-clk, devicetree,
	linux-kernel, linux-pci, linux-mediatek, linux-phy,
	linux-arm-kernel

Add clock/reset and PCIe support to EcoNet EN751221 and related SoCs.
This builds on the Airoha EN7523 clock driver and the Mediatek PCIe driver.

Patch 6 is upstreaming of Ahmed Naseef's work on EcoNet PCIe, which was
developed to support the EN7528, but which works equally on the EN751221.

There is also a workaround in patch 7 to gracefully handle PCI hardware
which does not advertize a bridge window and instead always reads zero.

Caleb James DeLisle (8):
  dt-bindings: clock, reset: Add econet EN751221 bindings
  clk: airoha: Add econet EN751221 clock/reset support to en7523-scu
  dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528
  phy: econet: Add PCIe PHY driver for EcoNet EN751221 and EN7528 SoCs.
  dt-bindings: PCI: mediatek: Add support for EcoNet EN7528
  PCI: mediatek: Add support for EcoNet EN7528 SoC
  PCI: Skip bridge window reads when window is not supported
  mips: dts: Add PCIe to EcoNet EN751221

 .../bindings/clock/airoha,en7523-scu.yaml     |  19 +-
 .../mips/econet,en751221-chip-scu.yaml        |  41 +++
 .../bindings/pci/mediatek-pcie.yaml           |   1 +
 .../phy/econet,en751221-pcie-phy.yaml         |  57 +++++
 MAINTAINERS                                   |  10 +
 arch/mips/boot/dts/econet/en751221.dtsi       | 114 +++++++++
 .../econet/en751221_smartfiber_xp8421-b.dts   |  21 ++
 arch/mips/econet/Kconfig                      |   2 +
 drivers/clk/Kconfig                           |   6 +-
 drivers/clk/clk-en7523.c                      | 236 +++++++++++++++++-
 drivers/pci/controller/Kconfig                |   2 +-
 drivers/pci/controller/pcie-mediatek.c        | 107 ++++++++
 drivers/pci/probe.c                           |   6 +
 drivers/phy/Kconfig                           |  12 +
 drivers/phy/Makefile                          |   1 +
 drivers/phy/phy-econet-pcie.c                 | 180 +++++++++++++
 .../dt-bindings/clock/econet,en751221-scu.h   |  15 ++
 .../dt-bindings/reset/econet,en751221-scu.h   |  49 ++++
 18 files changed, 869 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml
 create mode 100644 Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml
 create mode 100644 drivers/phy/phy-econet-pcie.c
 create mode 100644 include/dt-bindings/clock/econet,en751221-scu.h
 create mode 100644 include/dt-bindings/reset/econet,en751221-scu.h


base-commit: 3fa5e5702a82d259897bd7e209469bc06368bf31
-- 
2.39.5


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Vijay Kumar Tumati @ 2026-03-03 18:58 UTC (permalink / raw)
  To: Bryan O'Donoghue, Bryan O'Donoghue, Vinod Koul,
	Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Neil Armstrong
  Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media,
	devicetree, linux-kernel
In-Reply-To: <4440a3a8-7281-4bea-bb84-7a9d19ef7ce9@oss.qualcomm.com>



On 3/3/2026 10:08 AM, Vijay Kumar Tumati wrote:
> 
> 
> On 3/3/2026 1:27 AM, Bryan O'Donoghue wrote:
>> On 03/03/2026 01:51, Vijay Kumar Tumati wrote:
>>> Hi Bryan,
>>>
>>> On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote:
>>>> Add a base schema initially compatible with x1e80100 to describe 
>>>> MIPI CSI2
>>>> PHY devices.
>>>>
>>>> The hardware can support both C-PHY and D-PHY modes. The CSIPHY devices
>>>> have their own pinouts on the SoC as well as their own individual 
>>>> voltage
>>>> rails.
>>>>
>>>> The need to model voltage rails on a per-PHY basis leads us to define
>>>> CSIPHY devices as individual nodes.
>>>>
>>>> Two nice outcomes in terms of schema and DT arise from this change.
>>>>
>>>> 1. The ability to define on a per-PHY basis voltage rails.
>>>> 2. The ability to require those voltage.
>>>>
>>>> We have had a complete bodge upstream for this where a single set of
>>>> voltage rail for all CSIPHYs has been buried inside of CAMSS.
>>>>
>>>> Much like the I2C bus which is dedicated to Camera sensors - the CCI 
>>>> bus in
>>>> CAMSS parlance, the CSIPHY devices should be individually modelled.
>>>>
>>>> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>>>> ---
>>>>    .../bindings/phy/qcom,x1e80100-csi2-phy.yaml       | 114 ++++++++ 
>>>> + ++++++++++++
>>>>    1 file changed, 114 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100- 
>>>> csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100- 
>>>> csi2-phy.yaml
>>>> new file mode 100644
>>>> index 0000000000000..c937d26ccbda9
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml
>>>> @@ -0,0 +1,114 @@
>>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>>> +%YAML 1.2
>>>> +---
>>>> +$id: http://devicetree.org/schemas/phy/qcom,x1e80100-csi2-phy.yaml#
>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>> +
>>>> +title: Qualcomm CSI2 PHY
>>>> +
>>>> +maintainers:
>>>> +  - Bryan O'Donoghue <bod@kernel.org>
>>>> +
>>>> +description:
>>>> +  Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI 
>>>> CSI2 sensors
>>>> +  to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and 
>>>> D-PHY
>>>> +  modes.
>>>> +
>>>> +properties:
>>>> +  compatible:
>>>> +    const: qcom,x1e80100-csi2-phy
>>>> +
>>>> +  reg:
>>>> +    maxItems: 1
>>>> +
>>>> +  "#phy-cells":
>>>> +    const: 1
>>>> +
>>>> +  clocks:
>>>> +    maxItems: 4
>>>> +
>>>> +  clock-names:
>>>> +    items:
>>>> +      - const: csiphy
>>>> +      - const: csiphy_timer
>>>> +      - const: camnoc_axi
>>>> +      - const: cpas_ahb
>>>> +
>>>> +  interrupts:
>>>> +    maxItems: 1
>>>> +
>>>> +  operating-points-v2:
>>>> +    maxItems: 1
>>>> +
>>>> +  power-domains:
>>>> +    maxItems: 1
>>>> +
>>>> +  vdda-0p8-supply:
>>>> +    description: Phandle to a 0.8V regulator supply to a PHY.
>>>> +
>>>> +  vdda-1p2-supply:
>>>> +    description: Phandle to 1.2V regulator supply to a PHY.
>>>> +
>>>> +required:
>>>> +  - compatible
>>>> +  - reg
>>>> +  - "#phy-cells"
>>>> +  - clocks
>>>> +  - clock-names
>>>> +  - interrupts
>>>> +  - operating-points-v2
>>>> +  - power-domains
>>>> +  - vdda-0p8-supply
>>>> +  - vdda-1p2-supply
>>>> +
>>>> +additionalProperties: false
>>>> +
>>>> +examples:
>>>> +  - |
>>>> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
>>>> +    #include <dt-bindings/clock/qcom,x1e80100-camcc.h>
>>>> +    #include <dt-bindings/clock/qcom,x1e80100-gcc.h>
>>>> +    #include <dt-bindings/phy/phy.h>
>>>> +
>>>> +    csiphy@ace4000 {
>>>> +        compatible = "qcom,x1e80100-csi2-phy";
>>>> +        reg = <0x0ace4000 0x2000>;
>>>> +        #phy-cells = <1>;
>>>> +
>>>> +        clocks = <&camcc CAM_CC_CSIPHY0_CLK>,
>>>> +                 <&camcc CAM_CC_CSI0PHYTIMER_CLK>,
>>>> +                 <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>,
>>>> +                 <&camcc CAM_CC_CPAS_AHB_CLK>;
>>>> +        clock-names = "csiphy",
>>>> +                      "csiphy_timer",
>>>> +                      "camnoc_axi",
>>>> +                      "cpas_ahb";
>>>> +
>>>> +        operating-points-v2 = <&csiphy_opp_table>;
>>>> +
>>>> +        interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>;
>>>> +
>>>> +        power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>;
>>> As we are cleaning up the PHY device nodes, we should consider fixing
>>> the power domains as well. Although TOP GDSC is defined as a power
>>> domain, it is not the power source for the PHY devices. Rather, it is
>>> the MMCX, MXC and optionally MXA based on the architecture (Refer to
>>> 'Voltage rail' column for PHY clocks in IPCAT). 
>>
>> Feel free to send me a qcom laptop and I will :)
> :)
>>
>>  From memory though I _thought_ only the TOP was required for the PHY. 
>> I'd be grateful if you could confirm yourself in ipcat.
>>
>> - TITAN_TOP_GDSC
>> - MXC
>> - MMCX
>> - MXA - first time I've heard of this rail, from memory I don't remember
>>          having seen this in ipcat when I could do so.
> MCX and MMCX are comminly required power domains across the PHYs but a 
> subset of PHYs have the dependency on MXA.
Actually, it's a bit more complicated on this target as 
cam_cc_cphy_rx_clk_src also depends on MXA, which means all the CBCs 
connected this RCG do as well.
>>
>> There is no
>>> parent-child relationship between the TOP GDSC and these in the clock
>>> driver and it was just working as the required power rails are getting
>>> enabled by/for other MM devices.
>>
>> Well only the GDSC is supplied by the clock controller.
> Right, GDSC is controlled by the CAMCC to suspend the subsystems. But 
> the actual power supply and the voltage rails are under the control of 
> the RPMH. So the clients need to enable and vote for the required perf 
> corner as the core clocks scale up/down to be independent of the other 
> subsystems sharing those voltage rails.
>>
>>>> +
>>>> +        vdda-0p8-supply = <&vreg_l2c_0p8>;
>>>> +        vdda-1p2-supply = <&vreg_l1c_1p2>;
>>>> +    };
>>>> +
>>>> +    csiphy_opp_table: opp-table-csiphy {
>>>> +        compatible = "operating-points-v2";
>>>> +
>>>> +        opp-300000000 {
>>>> +            opp-hz = /bits/ 64 <300000000>;
>>>> +            required-opps = <&rpmhpd_opp_low_svs_d1>;
>>>> +        };
>>>> +
>>>> +        opp-400000000 {
>>>> +            opp-hz = /bits/ 64 <400000000>;
>>>> +            required-opps = <&rpmhpd_opp_low_svs>;
>>>> +        };
>>>> +
>>>> +        opp-480000000 {
>>>> +            opp-hz = /bits/ 64 <480000000>;
>>>> +            required-opps = <&rpmhpd_opp_low_svs>;
>>>> +        };
>>>> +    };
>>>>
>>> Thanks,
>>> Vijay.
>>
> Thanks,
> Vijay.


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Vijay Kumar Tumati @ 2026-03-03 18:08 UTC (permalink / raw)
  To: Bryan O'Donoghue, Bryan O'Donoghue, Vinod Koul,
	Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Neil Armstrong
  Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media,
	devicetree, linux-kernel
In-Reply-To: <03b44922-72d5-465b-96e1-97a19655e97d@kernel.org>



On 3/3/2026 1:27 AM, Bryan O'Donoghue wrote:
> On 03/03/2026 01:51, Vijay Kumar Tumati wrote:
>> Hi Bryan,
>>
>> On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote:
>>> Add a base schema initially compatible with x1e80100 to describe MIPI 
>>> CSI2
>>> PHY devices.
>>>
>>> The hardware can support both C-PHY and D-PHY modes. The CSIPHY devices
>>> have their own pinouts on the SoC as well as their own individual 
>>> voltage
>>> rails.
>>>
>>> The need to model voltage rails on a per-PHY basis leads us to define
>>> CSIPHY devices as individual nodes.
>>>
>>> Two nice outcomes in terms of schema and DT arise from this change.
>>>
>>> 1. The ability to define on a per-PHY basis voltage rails.
>>> 2. The ability to require those voltage.
>>>
>>> We have had a complete bodge upstream for this where a single set of
>>> voltage rail for all CSIPHYs has been buried inside of CAMSS.
>>>
>>> Much like the I2C bus which is dedicated to Camera sensors - the CCI 
>>> bus in
>>> CAMSS parlance, the CSIPHY devices should be individually modelled.
>>>
>>> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>>> ---
>>>    .../bindings/phy/qcom,x1e80100-csi2-phy.yaml       | 114 +++++++++ 
>>> ++++++++++++
>>>    1 file changed, 114 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100- 
>>> csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100- 
>>> csi2-phy.yaml
>>> new file mode 100644
>>> index 0000000000000..c937d26ccbda9
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml
>>> @@ -0,0 +1,114 @@
>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/phy/qcom,x1e80100-csi2-phy.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: Qualcomm CSI2 PHY
>>> +
>>> +maintainers:
>>> +  - Bryan O'Donoghue <bod@kernel.org>
>>> +
>>> +description:
>>> +  Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 
>>> sensors
>>> +  to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and 
>>> D-PHY
>>> +  modes.
>>> +
>>> +properties:
>>> +  compatible:
>>> +    const: qcom,x1e80100-csi2-phy
>>> +
>>> +  reg:
>>> +    maxItems: 1
>>> +
>>> +  "#phy-cells":
>>> +    const: 1
>>> +
>>> +  clocks:
>>> +    maxItems: 4
>>> +
>>> +  clock-names:
>>> +    items:
>>> +      - const: csiphy
>>> +      - const: csiphy_timer
>>> +      - const: camnoc_axi
>>> +      - const: cpas_ahb
>>> +
>>> +  interrupts:
>>> +    maxItems: 1
>>> +
>>> +  operating-points-v2:
>>> +    maxItems: 1
>>> +
>>> +  power-domains:
>>> +    maxItems: 1
>>> +
>>> +  vdda-0p8-supply:
>>> +    description: Phandle to a 0.8V regulator supply to a PHY.
>>> +
>>> +  vdda-1p2-supply:
>>> +    description: Phandle to 1.2V regulator supply to a PHY.
>>> +
>>> +required:
>>> +  - compatible
>>> +  - reg
>>> +  - "#phy-cells"
>>> +  - clocks
>>> +  - clock-names
>>> +  - interrupts
>>> +  - operating-points-v2
>>> +  - power-domains
>>> +  - vdda-0p8-supply
>>> +  - vdda-1p2-supply
>>> +
>>> +additionalProperties: false
>>> +
>>> +examples:
>>> +  - |
>>> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
>>> +    #include <dt-bindings/clock/qcom,x1e80100-camcc.h>
>>> +    #include <dt-bindings/clock/qcom,x1e80100-gcc.h>
>>> +    #include <dt-bindings/phy/phy.h>
>>> +
>>> +    csiphy@ace4000 {
>>> +        compatible = "qcom,x1e80100-csi2-phy";
>>> +        reg = <0x0ace4000 0x2000>;
>>> +        #phy-cells = <1>;
>>> +
>>> +        clocks = <&camcc CAM_CC_CSIPHY0_CLK>,
>>> +                 <&camcc CAM_CC_CSI0PHYTIMER_CLK>,
>>> +                 <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>,
>>> +                 <&camcc CAM_CC_CPAS_AHB_CLK>;
>>> +        clock-names = "csiphy",
>>> +                      "csiphy_timer",
>>> +                      "camnoc_axi",
>>> +                      "cpas_ahb";
>>> +
>>> +        operating-points-v2 = <&csiphy_opp_table>;
>>> +
>>> +        interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>;
>>> +
>>> +        power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>;
>> As we are cleaning up the PHY device nodes, we should consider fixing
>> the power domains as well. Although TOP GDSC is defined as a power
>> domain, it is not the power source for the PHY devices. Rather, it is
>> the MMCX, MXC and optionally MXA based on the architecture (Refer to
>> 'Voltage rail' column for PHY clocks in IPCAT). 
> 
> Feel free to send me a qcom laptop and I will :)
:)
> 
>  From memory though I _thought_ only the TOP was required for the PHY. 
> I'd be grateful if you could confirm yourself in ipcat.
> 
> - TITAN_TOP_GDSC
> - MXC
> - MMCX
> - MXA - first time I've heard of this rail, from memory I don't remember
>          having seen this in ipcat when I could do so.
MCX and MMCX are comminly required power domains across the PHYs but a 
subset of PHYs have the dependency on MXA.
> 
> There is no
>> parent-child relationship between the TOP GDSC and these in the clock
>> driver and it was just working as the required power rails are getting
>> enabled by/for other MM devices.
> 
> Well only the GDSC is supplied by the clock controller.
Right, GDSC is controlled by the CAMCC to suspend the subsystems. But 
the actual power supply and the voltage rails are under the control of 
the RPMH. So the clients need to enable and vote for the required perf 
corner as the core clocks scale up/down to be independent of the other 
subsystems sharing those voltage rails.
> 
>>> +
>>> +        vdda-0p8-supply = <&vreg_l2c_0p8>;
>>> +        vdda-1p2-supply = <&vreg_l1c_1p2>;
>>> +    };
>>> +
>>> +    csiphy_opp_table: opp-table-csiphy {
>>> +        compatible = "operating-points-v2";
>>> +
>>> +        opp-300000000 {
>>> +            opp-hz = /bits/ 64 <300000000>;
>>> +            required-opps = <&rpmhpd_opp_low_svs_d1>;
>>> +        };
>>> +
>>> +        opp-400000000 {
>>> +            opp-hz = /bits/ 64 <400000000>;
>>> +            required-opps = <&rpmhpd_opp_low_svs>;
>>> +        };
>>> +
>>> +        opp-480000000 {
>>> +            opp-hz = /bits/ 64 <480000000>;
>>> +            required-opps = <&rpmhpd_opp_low_svs>;
>>> +        };
>>> +    };
>>>
>> Thanks,
>> Vijay.
> 
Thanks,
Vijay.

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Vijay Kumar Tumati @ 2026-03-03 18:03 UTC (permalink / raw)
  To: Bryan O'Donoghue, Bryan O'Donoghue, Bryan O'Donoghue,
	Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Neil Armstrong
  Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media,
	devicetree, linux-kernel
In-Reply-To: <676e2a9f-d274-40fa-988f-e9388ba40f71@nxsw.ie>



On 3/3/2026 1:30 AM, Bryan O'Donoghue wrote:
> On 03/03/2026 09:27, Bryan O'Donoghue wrote:
>> - MXA - first time I've heard of this rail, from memory I don't remember
>>           having seen this in ipcat when I could do so.
> 
> Yeah no MXA isn't a required vote.
> 
> https://lore.kernel.org/linux-arm-msm/9ff1645f-b2c9-4c1a-ae2d-96af416b08d9@oss.qualcomm.com/
If I am not wrong, CAMCC only enables the power domains that source the 
CAMCC block and it's register access. And for that, it only needs those 
power domains to be just enabled without any performance vote. Based on 
her comment, if MXA is always enabled (at min level), probably CAMCC 
driver doesn't need to enable or scale it explicitly. However, the 
camera devices that actually depend on this power domain for their core 
functionality need to scale this per the core clock corner. I can double 
check though.
> 
> ---
> bod
> 
Thanks,
Vijay.


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* [PATCH net-next v2 7/7] net: stmmac: qcom-ethqos: remove phy_set_mode_ext() after phy_power_on()
From: Russell King (Oracle) @ 2026-03-03 15:54 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
	linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
	Paolo Abeni, Vinod Koul
In-Reply-To: <aacD3osfaZkLsGxm@shell.armlinux.org.uk>

The call to phy_set_mode_ext() after phy_power_on() was a work-around
for the qcom-sgmii-eth SerDes driver that only re-enabled its clocks on
phy_power_on() but did not configure the PHY. Now that the SerDes driver
fully configures the SerDes at phy_power_on(), there is no need to call
phy_set_mode_ext() immediately afterwards.

This also means we no longer need to record the previous operating mode
of the driver - this is up to the SerDes driver. In any case, the only
thing that we care about is the SerDes provides the necessary clocks to
the stmmac core to allow it to reset at this point. The actual mode is
irrelevant at this point as the correct mode will be configured in
ethqos_mac_finish_serdes() just before the network device is brought
online.

Reviewed-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
 .../stmicro/stmmac/dwmac-qcom-ethqos.c         | 18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 8913f6f02b9e..cb1c074c2053 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -105,7 +105,6 @@ struct qcom_ethqos {
 
 	struct clk *link_clk;
 	struct phy *serdes_phy;
-	phy_interface_t serdes_mode;
 	phy_interface_t phy_mode;
 
 	const struct ethqos_emac_por *rgmii_por;
@@ -648,17 +647,8 @@ static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv)
 		return ret;
 
 	ret = phy_power_on(ethqos->serdes_phy);
-	if (ret) {
-		phy_exit(ethqos->serdes_phy);
-		return ret;
-	}
-
-	ret = phy_set_mode_ext(ethqos->serdes_phy, PHY_MODE_ETHERNET,
-			       ethqos->serdes_mode);
-	if (ret) {
-		phy_power_off(ethqos->serdes_phy);
+	if (ret)
 		phy_exit(ethqos->serdes_phy);
-	}
 
 	return ret;
 }
@@ -681,12 +671,9 @@ static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv,
 	qcom_ethqos_set_sgmii_loopback(ethqos, false);
 
 	if (interface == PHY_INTERFACE_MODE_SGMII ||
-	    interface == PHY_INTERFACE_MODE_2500BASEX) {
+	    interface == PHY_INTERFACE_MODE_2500BASEX)
 		ret = phy_set_mode_ext(ethqos->serdes_phy, PHY_MODE_ETHERNET,
 				       interface);
-		if (ret == 0)
-			ethqos->serdes_mode = interface;
-	}
 
 	return ret;
 }
@@ -839,7 +826,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
 		plat_dat->host_dma_width = data->dma_addr_width;
 
 	if (ethqos->serdes_phy) {
-		ethqos->serdes_mode = PHY_INTERFACE_MODE_SGMII;
 		plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup;
 		plat_dat->serdes_powerdown  = qcom_ethqos_serdes_powerdown;
 	}
-- 
2.47.3


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH net-next v2 5/7] phy: qcom-sgmii-eth: remove qcom_dwmac_sgmii_phy_interface()
From: Russell King (Oracle) @ 2026-03-03 15:53 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
	linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
	Paolo Abeni, Vinod Koul
In-Reply-To: <aacD3osfaZkLsGxm@shell.armlinux.org.uk>

Now that qcom_dwmac_sgmii_phy_interface() only serves to validate the
passed interface mode, combine it with qcom_dwmac_sgmii_phy_validate(),
and use qcom_dwmac_sgmii_phy_validate() to validate the mode in
qcom_dwmac_sgmii_phy_set_mode().

Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Acked-by: Vinod Koul <vkoul@kernel.org>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
 drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 27 +++++++++--------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index 58ff15601206..6332ff291fdf 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -290,7 +290,9 @@ static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
 	return 0;
 }
 
-static int qcom_dwmac_sgmii_phy_interface(enum phy_mode mode, int submode)
+static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode,
+					 int submode,
+					 union phy_configure_opts *opts)
 {
 	if (mode != PHY_MODE_ETHERNET)
 		return -EINVAL;
@@ -298,7 +300,7 @@ static int qcom_dwmac_sgmii_phy_interface(enum phy_mode mode, int submode)
 	if (submode == PHY_INTERFACE_MODE_SGMII ||
 	    submode == PHY_INTERFACE_MODE_1000BASEX ||
 	    submode == PHY_INTERFACE_MODE_2500BASEX)
-		return submode;
+		return 0;
 
 	return -EINVAL;
 }
@@ -307,27 +309,18 @@ static int qcom_dwmac_sgmii_phy_set_mode(struct phy *phy, enum phy_mode mode,
 					 int submode)
 {
 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
-	int interface;
+	int ret;
 
-	interface = qcom_dwmac_sgmii_phy_interface(mode, submode);
-	if (interface < 0)
-		return interface;
+	ret = qcom_dwmac_sgmii_phy_validate(phy, mode, submode, NULL);
+	if (ret)
+		return ret;
 
-	if (interface != data->interface)
-		data->interface = interface;
+	if (submode != data->interface)
+		data->interface = submode;
 
 	return qcom_dwmac_sgmii_phy_calibrate(phy);
 }
 
-static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode,
-					 int submode,
-					 union phy_configure_opts *opts)
-{
-	int ret = qcom_dwmac_sgmii_phy_interface(mode, submode);
-
-	return ret < 0 ? ret : 0;
-}
-
 static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
 	.power_on	= qcom_dwmac_sgmii_phy_power_on,
 	.power_off	= qcom_dwmac_sgmii_phy_power_off,
-- 
2.47.3


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH net-next v2 6/7] phy: qcom-sgmii-eth: relax order of .power_on() vs .set_mode*()
From: Russell King (Oracle) @ 2026-03-03 15:54 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
	linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
	Paolo Abeni, Vinod Koul
In-Reply-To: <aacD3osfaZkLsGxm@shell.armlinux.org.uk>

Allow any order of the .power_on() and .set_mode*() methods as per the
recent discussion. This means phy_power_on() with this SerDes will now
restore the previous setup without requiring a subsequent
phy_set_mode*() call.

Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Acked-by: Vinod Koul <vkoul@kernel.org>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
 drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index 6332ff291fdf..f48faa2929a6 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -271,8 +271,17 @@ static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
 static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy)
 {
 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+	int ret;
+
+	ret = clk_prepare_enable(data->refclk);
+	if (ret < 0)
+		return ret;
 
-	return clk_prepare_enable(data->refclk);
+	ret = qcom_dwmac_sgmii_phy_calibrate(phy);
+	if (ret < 0)
+		clk_disable_unprepare(data->refclk);
+
+	return ret;
 }
 
 static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
@@ -318,6 +327,9 @@ static int qcom_dwmac_sgmii_phy_set_mode(struct phy *phy, enum phy_mode mode,
 	if (submode != data->interface)
 		data->interface = submode;
 
+	if (phy->power_count == 0)
+		return 0;
+
 	return qcom_dwmac_sgmii_phy_calibrate(phy);
 }
 
-- 
2.47.3


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH net-next v2 4/7] phy: qcom-sgmii-eth: use PHY interface mode for SerDes settings
From: Russell King (Oracle) @ 2026-03-03 15:53 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
	linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
	Paolo Abeni, Vinod Koul
In-Reply-To: <aacD3osfaZkLsGxm@shell.armlinux.org.uk>

As established in the previous commit, using SPEED_1000 and SPEED_2500
does not make sense for a SerDes due to the PCS encoding that is used
over the SerDes link, which inflates the data rate at the SerDes. Thus,
the use of these constants in a SerDes driver is incorrect.

Since qcom-sgmii-eth no longer implements phy_set_speed(), but instead
uses the PHY interface mode passed via the .set_mode() method, convert
the driver to use the PHY interface mode internally to decide whether
to configure the SerDes for 1.25Gbps or 3.125Gbps mode.

Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Acked-by: Vinod Koul <vkoul@kernel.org>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
 drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 41 ++++++++++++-----------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index dcfdb7d0e8ea..58ff15601206 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -29,7 +29,7 @@
 struct qcom_dwmac_sgmii_phy_data {
 	struct regmap *regmap;
 	struct clk *refclk;
-	int speed;
+	phy_interface_t interface;
 };
 
 static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)
@@ -223,15 +223,18 @@ static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
 	struct device *dev = phy->dev.parent;
 
-	switch (data->speed) {
-	case SPEED_10:
-	case SPEED_100:
-	case SPEED_1000:
+	switch (data->interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_1000BASEX:
+		/* 1.25Gbps mode */
 		qcom_dwmac_sgmii_phy_init_1g(data->regmap);
 		break;
-	case SPEED_2500:
+	case PHY_INTERFACE_MODE_2500BASEX:
+		/* 3.125Gbps mode */
 		qcom_dwmac_sgmii_phy_init_2p5g(data->regmap);
 		break;
+	default:
+		return -EINVAL;
 	}
 
 	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
@@ -287,17 +290,15 @@ static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
 	return 0;
 }
 
-static int qcom_dwmac_sgmii_phy_speed(enum phy_mode mode, int submode)
+static int qcom_dwmac_sgmii_phy_interface(enum phy_mode mode, int submode)
 {
 	if (mode != PHY_MODE_ETHERNET)
 		return -EINVAL;
 
 	if (submode == PHY_INTERFACE_MODE_SGMII ||
-	    submode == PHY_INTERFACE_MODE_1000BASEX)
-		return SPEED_1000;
-
-	if (submode == PHY_INTERFACE_MODE_2500BASEX)
-		return SPEED_2500;
+	    submode == PHY_INTERFACE_MODE_1000BASEX ||
+	    submode == PHY_INTERFACE_MODE_2500BASEX)
+		return submode;
 
 	return -EINVAL;
 }
@@ -306,14 +307,14 @@ static int qcom_dwmac_sgmii_phy_set_mode(struct phy *phy, enum phy_mode mode,
 					 int submode)
 {
 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
-	int speed;
+	int interface;
 
-	speed = qcom_dwmac_sgmii_phy_speed(mode, submode);
-	if (speed < 0)
-		return speed;
+	interface = qcom_dwmac_sgmii_phy_interface(mode, submode);
+	if (interface < 0)
+		return interface;
 
-	if (speed != data->speed)
-		data->speed = speed;
+	if (interface != data->interface)
+		data->interface = interface;
 
 	return qcom_dwmac_sgmii_phy_calibrate(phy);
 }
@@ -322,7 +323,7 @@ static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode,
 					 int submode,
 					 union phy_configure_opts *opts)
 {
-	int ret = qcom_dwmac_sgmii_phy_speed(mode, submode);
+	int ret = qcom_dwmac_sgmii_phy_interface(mode, submode);
 
 	return ret < 0 ? ret : 0;
 }
@@ -356,7 +357,7 @@ static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
 	if (!data)
 		return -ENOMEM;
 
-	data->speed = SPEED_10;
+	data->interface = PHY_INTERFACE_MODE_SGMII;
 
 	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
-- 
2.47.3


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH net-next v2 3/7] phy: qcom-sgmii-eth: remove .set_speed() implementation
From: Russell King (Oracle) @ 2026-03-03 15:53 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
	linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
	Paolo Abeni, Vinod Koul
In-Reply-To: <aacD3osfaZkLsGxm@shell.armlinux.org.uk>

Now that the qcom-ethqos driver has migrated to use phy_set_mode_ext()
rather than phy_set_speed() to configure the SerDes, the support for
phy_set_speed() is now obsolete. Remove support for this method.

Using the MAC speed for the SerDes is never correct due to the PCS
encoding. For SGMII and 2500BASE-X, the PCS uses 8B10B encoding, and
so:

  MAC rate * PCS output bits / PCS input bits = SerDes rate
   1000M   *       10        /       8        = 1250M
   2500M   *       10        /       8        = 3125M

Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Acked-by: Vinod Koul <vkoul@kernel.org>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
 drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index 4ea3dce7719f..dcfdb7d0e8ea 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -318,16 +318,6 @@ static int qcom_dwmac_sgmii_phy_set_mode(struct phy *phy, enum phy_mode mode,
 	return qcom_dwmac_sgmii_phy_calibrate(phy);
 }
 
-static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
-{
-	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
-
-	if (speed != data->speed)
-		data->speed = speed;
-
-	return qcom_dwmac_sgmii_phy_calibrate(phy);
-}
-
 static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode,
 					 int submode,
 					 union phy_configure_opts *opts)
@@ -341,7 +331,6 @@ static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
 	.power_on	= qcom_dwmac_sgmii_phy_power_on,
 	.power_off	= qcom_dwmac_sgmii_phy_power_off,
 	.set_mode	= qcom_dwmac_sgmii_phy_set_mode,
-	.set_speed	= qcom_dwmac_sgmii_phy_set_speed,
 	.validate	= qcom_dwmac_sgmii_phy_validate,
 	.calibrate	= qcom_dwmac_sgmii_phy_calibrate,
 	.owner		= THIS_MODULE,
-- 
2.47.3


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH net-next v2 2/7] net: stmmac: qcom-ethqos: convert to use phy_set_mode_ext()
From: Russell King (Oracle) @ 2026-03-03 15:53 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
	linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
	Paolo Abeni, Vinod Koul
In-Reply-To: <aacD3osfaZkLsGxm@shell.armlinux.org.uk>

qcom-sgmii-eth now accepts the phy_set_mode*() calls to configure the
SerDes, taking a PHY interface mode rather than a speed. This allows
the elimination of the interface mode to speed conversion in
ethqos_mac_finish_serdes().

Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
 .../stmicro/stmmac/dwmac-qcom-ethqos.c        | 23 ++++++++-----------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 57cbe800f652..8913f6f02b9e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -105,7 +105,7 @@ struct qcom_ethqos {
 
 	struct clk *link_clk;
 	struct phy *serdes_phy;
-	int serdes_speed;
+	phy_interface_t serdes_mode;
 	phy_interface_t phy_mode;
 
 	const struct ethqos_emac_por *rgmii_por;
@@ -653,7 +653,8 @@ static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv)
 		return ret;
 	}
 
-	ret = phy_set_speed(ethqos->serdes_phy, ethqos->serdes_speed);
+	ret = phy_set_mode_ext(ethqos->serdes_phy, PHY_MODE_ETHERNET,
+			       ethqos->serdes_mode);
 	if (ret) {
 		phy_power_off(ethqos->serdes_phy);
 		phy_exit(ethqos->serdes_phy);
@@ -675,20 +676,16 @@ static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv,
 				    phy_interface_t interface)
 {
 	struct qcom_ethqos *ethqos = priv;
-	int speed, ret = 0;
+	int ret = 0;
 
 	qcom_ethqos_set_sgmii_loopback(ethqos, false);
 
-	speed = SPEED_UNKNOWN;
-	if (interface == PHY_INTERFACE_MODE_SGMII)
-		speed = SPEED_1000;
-	else if (interface == PHY_INTERFACE_MODE_2500BASEX)
-		speed = SPEED_2500;
-
-	if (speed != SPEED_UNKNOWN && speed != ethqos->serdes_speed) {
-		ret = phy_set_speed(ethqos->serdes_phy, speed);
+	if (interface == PHY_INTERFACE_MODE_SGMII ||
+	    interface == PHY_INTERFACE_MODE_2500BASEX) {
+		ret = phy_set_mode_ext(ethqos->serdes_phy, PHY_MODE_ETHERNET,
+				       interface);
 		if (ret == 0)
-			ethqos->serdes_speed = speed;
+			ethqos->serdes_mode = interface;
 	}
 
 	return ret;
@@ -819,7 +816,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(ethqos->serdes_phy),
 				     "Failed to get serdes phy\n");
 
-	ethqos->serdes_speed = SPEED_1000;
 	ethqos_set_clk_tx_rate(ethqos, NULL, plat_dat->phy_interface,
 			       SPEED_1000);
 
@@ -843,6 +839,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
 		plat_dat->host_dma_width = data->dma_addr_width;
 
 	if (ethqos->serdes_phy) {
+		ethqos->serdes_mode = PHY_INTERFACE_MODE_SGMII;
 		plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup;
 		plat_dat->serdes_powerdown  = qcom_ethqos_serdes_powerdown;
 	}
-- 
2.47.3


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH net-next v2 1/7] net: stmmac: qcom-ethqos: move ethqos_set_serdes_speed()
From: Russell King (Oracle) @ 2026-03-03 15:53 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
	linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
	Paolo Abeni, Vinod Koul
In-Reply-To: <aacD3osfaZkLsGxm@shell.armlinux.org.uk>

Combine ethqos_set_serdes_speed() with ethqos_mac_finish_serdes() to
simplify the code.

Reviewed-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
 .../stmicro/stmmac/dwmac-qcom-ethqos.c        | 22 +++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index ad5b5d950fff..57cbe800f652 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -591,14 +591,6 @@ static void ethqos_configure_rgmii(struct qcom_ethqos *ethqos,
 	ethqos_rgmii_macro_init(ethqos, speed);
 }
 
-static void ethqos_set_serdes_speed(struct qcom_ethqos *ethqos, int speed)
-{
-	if (ethqos->serdes_speed != speed) {
-		phy_set_speed(ethqos->serdes_phy, speed);
-		ethqos->serdes_speed = speed;
-	}
-}
-
 static void ethqos_pcs_set_inband(struct stmmac_priv *priv, bool enable)
 {
 	stmmac_pcs_ctrl_ane(priv, enable, 0);
@@ -683,15 +675,23 @@ static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv,
 				    phy_interface_t interface)
 {
 	struct qcom_ethqos *ethqos = priv;
+	int speed, ret = 0;
 
 	qcom_ethqos_set_sgmii_loopback(ethqos, false);
 
+	speed = SPEED_UNKNOWN;
 	if (interface == PHY_INTERFACE_MODE_SGMII)
-		ethqos_set_serdes_speed(ethqos, SPEED_1000);
+		speed = SPEED_1000;
 	else if (interface == PHY_INTERFACE_MODE_2500BASEX)
-		ethqos_set_serdes_speed(ethqos, SPEED_2500);
+		speed = SPEED_2500;
 
-	return 0;
+	if (speed != SPEED_UNKNOWN && speed != ethqos->serdes_speed) {
+		ret = phy_set_speed(ethqos->serdes_phy, speed);
+		if (ret == 0)
+			ethqos->serdes_speed = speed;
+	}
+
+	return ret;
 }
 
 static int ethqos_clks_config(void *priv, bool enabled)
-- 
2.47.3


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH net-next v2 0/7] net: stmmac: qcom-ethqos: further serdes reorganisation
From: Russell King (Oracle) @ 2026-03-03 15:53 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
	linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
	Paolo Abeni, Vinod Koul

This is part 2 of the qcom-ethqos series, part 1 and patch 2 of part 2
has now been merged.

This part of the series focuses on the generic PHY driver, but these
changes have dependencies on the ethernet driver, hence why
it will need to go via net-next. Furthermore, subsequent changes
depend on these patches.

The underlying ideas here are:

- get rid of the driver using phy_set_speed() with SPEED_1000 and
  SPEED_2500 which makes no sense for an ethernet SerDes due to the
  PCS 8B10B data encoding, which inflates the data rate at the SerDes
  compared to the MAC. This is replaced with phy_set_mode_ext().
- allow phy_power_on() / phy_set_mode*() to be called in any order.

Mohd has tested this series, although not in the resulting merge order.

Changes since resend2:
- Drop patch 2 as that is now applied
- Add Vinod's Acks, which were eventually sent in response to the first
  posting of this series.

 .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c    | 31 +++------
 drivers/phy/qualcomm/phy-qcom-sgmii-eth.c          | 73 ++++++++++------------
 2 files changed, 41 insertions(+), 63 deletions(-)

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Bryan O'Donoghue @ 2026-03-03 14:56 UTC (permalink / raw)
  To: Konrad Dybcio, Bryan O'Donoghue, Bryan O'Donoghue,
	Vijay Kumar Tumati, Vinod Koul, Kishon Vijay Abraham I,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong
  Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media,
	devicetree, linux-kernel
In-Reply-To: <04f22394-2dbb-4b7b-bce3-9b41ebfb7709@oss.qualcomm.com>

On 03/03/2026 12:34, Konrad Dybcio wrote:
> That depends on the use case.
> 
> MXA is always-on (that's the 'A' in the name, as opposed to 'C'
> for 'Collapsible'), but it's not always at the required performance
> state (svs, nom, etc.). For some clock controllers specifically, there
> is no need to put them into the picture, as the rail may be unconnected
> altogether, or only used for some retention mechanisms (which only
> require the rail to be enabled and nothing more)

Does this rail have an OPP table you can share ?

---
bod

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v3 5/6] drm/mediatek: dsi: Add compatible for mt8167-dsi
From: AngeloGioacchino Del Regno @ 2026-03-03 14:24 UTC (permalink / raw)
  To: CK Hu (胡俊光), l.scorcia@gmail.com,
	krzk+dt@kernel.org
  Cc: robh@kernel.org, Chunfeng Yun (云春峰),
	simona@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org,
	linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	dri-devel@lists.freedesktop.org, chunkuang.hu@kernel.org,
	vkoul@kernel.org, devicetree@vger.kernel.org,
	linux-phy@lists.infradead.org, p.zabel@pengutronix.de,
	conor+dt@kernel.org, airlied@gmail.com,
	linux-arm-kernel@lists.infradead.org,
	maarten.lankhorst@linux.intel.com, matthias.bgg@gmail.com,
	neil.armstrong@linaro.org
In-Reply-To: <dcb797934bdb4467037559ee5e91bee0a568c03a.camel@mediatek.com>

Il 03/03/26 08:56, CK Hu (胡俊光) ha scritto:
> On Wed, 2026-02-25 at 09:15 +0100, Luca Leonardo Scorcia wrote:
>> External email : Please do not click links or open attachments until you have verified the sender or the content.
>>
>>
>>>> The mt8167 DSI controller is fully compatible with the one found in
>>>> mt2701. Device tree documentation is already present upstream.
>>>
>>> If mt8167 DSI is fully compatible with mt2701 DSI, I think the binding document and device tree should be modified.
>>> In device tree,
>>>
>>>      compatible = "mediatek,mt8167-dsi", "mediatek,mt2701-dsi";
>>>
>>> And this patch is not necessary.
>>
>> Hi, if I understand your review correctly that's what v2 [1] of this
>> patch did, but the change was rejected during review.
>>
>> As far as I can see there is no win-win solution here. This tricky
>> situation derives from the fact that in last year's submissions the
>> change was only partially merged - the bindings went upstream while
>> the driver did not, and now we have to work around this. In v3 I tried
>> to address the issue by actually implementing what the binding
>> document says.
>> I'll be happy to resubmit v4 but I need to know what's the consensus here.
> 
> You mean Krzysztof's comment?
> He has two comment.
> The first is 'remove'. You actually not remove "mediatek,mt8167-dsi". You change it.
> The second is about fallback. I'm also not sure why he says it's NAK. Also a bad wording?
> After Angelo's comment, Krzysztof does not response.
> I also do not know what Krzysztof think.
> I agree with Angelo. Single "mediatek,mt8167-dsi" does not reflect the hardware compatible but fallback does.
> Maybe describe more information (hardware) to Krzysztof, and ask what's the better way to do.
> 

First of all: I would be happy with having

compatible = "mediatek,mt8167-dsi", "mediatek,mt2701-dsi";

in the devicetree, and to drop this patch - but that's not possible, check below.

The problem that Krzysztof was raising is that the bindings currently define
the "mediatek,mt8167-dsi" as single compatible with no fallback, and removing
it would break the ABI (as the bindings are not used only for Linux, but also
for bootloaders).

Even though I can try my best to convince him, this is a real problem: mistakes
were made in the past, and the only way to get the mt8167-dsi supported right
now is to, unfortunately, add the compatible in mtk_dsi.c.

I don't like that, and I see that you (CK) don't as well, but that's the result
of past mistakes... and apparently we can't do anything about this if not to
*uselessly clutter the driver* with that.

So, that said...

I'm sad to say that this patch is the only way to get this SoC probed by mtk_dsi
and that there's no other way around it, because the bindings maintainers are
forbidding us from removing the bad compatible (which was *never* used anyway)
from there and making it right with allowing it only under 2701 fallback.

I'm moving krzk to the To: field of this email in hope to get back a reply that
sounds like "you misunderstood me, you can do it", but I'm not positive about this.

Krzysztof, please confirm or deny what I said.

Regards,
Angelo


> Regards,
> CK
> 
>>
>> Thanks!
>>
>> [1] https://urldefense.com/v3/__https://patchwork.kernel.org/project/linux-mediatek/patch/ff920a7cc94f2b0c03d4bb55142030fded30d07c.1771258407.git.l.scorcia@gmail.com/__;!!CTRNKA9wMg0ARbw!lIBnCRkybM1oxoARb70JlLMPlXHKqW9dwSmVqXGsvj3LE9hsWuINkPgtrlr8Jl8-atOvzYoMjtavHOr3$
>>
>>>>
>>>> Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
>>>> ---
>>>>   drivers/gpu/drm/mediatek/mtk_dsi.c | 1 +
>>>>   1 file changed, 1 insertion(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>>> index af4871de9e4c..ad10e86b161d 100644
>>>> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
>>>> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>>> @@ -1301,6 +1301,7 @@ static const struct mtk_dsi_driver_data mt8188_dsi_driver_data = {
>>>>
>>>>   static const struct of_device_id mtk_dsi_of_match[] = {
>>>>          { .compatible = "mediatek,mt2701-dsi", .data = &mt2701_dsi_driver_data },
>>>> +       { .compatible = "mediatek,mt8167-dsi", .data = &mt2701_dsi_driver_data },
>>>>          { .compatible = "mediatek,mt8173-dsi", .data = &mt8173_dsi_driver_data },
>>>>          { .compatible = "mediatek,mt8183-dsi", .data = &mt8183_dsi_driver_data },
>>>>          { .compatible = "mediatek,mt8186-dsi", .data = &mt8186_dsi_driver_data },
>>>> --
>>>> 2.43.0
>>>>
>>>>
>> --
>> Luca Leonardo Scorcia
>> l.scorcia@gmail.com
> 



-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Konrad Dybcio @ 2026-03-03 12:34 UTC (permalink / raw)
  To: Bryan O'Donoghue, Bryan O'Donoghue, Vijay Kumar Tumati,
	Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong
  Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media,
	devicetree, linux-kernel
In-Reply-To: <676e2a9f-d274-40fa-988f-e9388ba40f71@nxsw.ie>

On 3/3/26 10:30 AM, Bryan O'Donoghue wrote:
> On 03/03/2026 09:27, Bryan O'Donoghue wrote:
>> - MXA - first time I've heard of this rail, from memory I don't remember
>>          having seen this in ipcat when I could do so.
> 
> Yeah no MXA isn't a required vote.

That depends on the use case.

MXA is always-on (that's the 'A' in the name, as opposed to 'C'
for 'Collapsible'), but it's not always at the required performance
state (svs, nom, etc.). For some clock controllers specifically, there
is no need to put them into the picture, as the rail may be unconnected
altogether, or only used for some retention mechanisms (which only
require the rail to be enabled and nothing more)

Konrad

> 
> https://lore.kernel.org/linux-arm-msm/9ff1645f-b2c9-4c1a-ae2d-96af416b08d9@oss.qualcomm.com/
> 
> ---
> bod
> 
> 

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply


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