* [PATCH v2 1/8] dt-bindings: clock, reset: Add econet EN751221
2026-03-09 13:18 [PATCH v2 0/8] mips: econet: Add clk/reset and PCIe support Caleb James DeLisle
@ 2026-03-09 13:18 ` Caleb James DeLisle
2026-03-10 8:21 ` Krzysztof Kozlowski
2026-03-09 13:18 ` [PATCH v2 2/8] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu Caleb James DeLisle
` (6 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-09 13:18 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 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 | 7 ++-
.../devicetree/bindings/mfd/syscon.yaml | 2 +
MAINTAINERS | 2 +
.../dt-bindings/clock/econet,en751221-scu.h | 13 +++++
.../dt-bindings/reset/econet,en751221-scu.h | 49 +++++++++++++++++++
5 files changed, 72 insertions(+), 1 deletion(-)
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..91abe7716fce 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,4 @@ examples:
#reset-cells = <1>;
};
};
+
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index e57add2bacd3..e22867088063 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -61,6 +61,7 @@ select:
- cirrus,ep7209-syscon2
- cirrus,ep7209-syscon3
- cnxt,cx92755-uc
+ - econet,en751221-chip-scu
- freecom,fsg-cs2-system-controller
- fsl,imx93-aonmix-ns-syscfg
- fsl,imx93-wakeupmix-syscfg
@@ -173,6 +174,7 @@ properties:
- cirrus,ep7209-syscon2
- cirrus,ep7209-syscon3
- cnxt,cx92755-uc
+ - econet,en751221-chip-scu
- freecom,fsg-cs2-system-controller
- fsl,imx93-aonmix-ns-syscfg
- fsl,imx93-wakeupmix-syscfg
diff --git a/MAINTAINERS b/MAINTAINERS
index 14899f1de77e..3781d55db5bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9119,6 +9119,8 @@ 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..44a5b197cb06
--- /dev/null
+++ b/include/dt-bindings/clock/econet,en751221-scu.h
@@ -0,0 +1,13 @@
+/* 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
+
+#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
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH v2 1/8] dt-bindings: clock, reset: Add econet EN751221
2026-03-09 13:18 ` [PATCH v2 1/8] dt-bindings: clock, reset: Add econet EN751221 Caleb James DeLisle
@ 2026-03-10 8:21 ` Krzysztof Kozlowski
2026-03-10 8:37 ` Caleb James DeLisle
0 siblings, 1 reply; 23+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-10 8:21 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
On Mon, Mar 09, 2026 at 01:18:11PM +0000, Caleb James DeLisle wrote:
> 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 | 7 ++-
> .../devicetree/bindings/mfd/syscon.yaml | 2 +
> MAINTAINERS | 2 +
> .../dt-bindings/clock/econet,en751221-scu.h | 13 +++++
> .../dt-bindings/reset/econet,en751221-scu.h | 49 +++++++++++++++++++
> 5 files changed, 72 insertions(+), 1 deletion(-)
> 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..91abe7716fce 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
751 < 752, keep alphanumeric order
>
> reg:
> items:
> @@ -67,7 +68,10 @@ allOf:
> - if:
> properties:
> compatible:
> - const: airoha,en7581-scu
> + items:
<form letter>
This is a friendly reminder during the review process.
It seems my or other reviewer's previous comments were not fully
addressed. Maybe the feedback got lost between the quotes, maybe you
just forgot to apply it. Please go back to the previous discussion and
either implement all requested changes or keep discussing them.
Thank you.
</form letter>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 1/8] dt-bindings: clock, reset: Add econet EN751221
2026-03-10 8:21 ` Krzysztof Kozlowski
@ 2026-03-10 8:37 ` Caleb James DeLisle
2026-03-10 8:51 ` Krzysztof Kozlowski
0 siblings, 1 reply; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-10 8:37 UTC (permalink / raw)
To: Krzysztof Kozlowski
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
On 10/03/2026 09:21, Krzysztof Kozlowski wrote:
> On Mon, Mar 09, 2026 at 01:18:11PM +0000, Caleb James DeLisle wrote:
>> 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 | 7 ++-
>> .../devicetree/bindings/mfd/syscon.yaml | 2 +
>> MAINTAINERS | 2 +
>> .../dt-bindings/clock/econet,en751221-scu.h | 13 +++++
>> .../dt-bindings/reset/econet,en751221-scu.h | 49 +++++++++++++++++++
>> 5 files changed, 72 insertions(+), 1 deletion(-)
>> 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..91abe7716fce 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
> 751 < 752, keep alphanumeric order
"econet," after "airoha," because e > a, of course I can order by number
if that's really what you want.
>
>>
>> reg:
>> items:
>> @@ -67,7 +68,10 @@ allOf:
>> - if:
>> properties:
>> compatible:
>> - const: airoha,en7581-scu
>> + items:
> <form letter>
> This is a friendly reminder during the review process.
My apologies, I missed this one when I was collecting notes and
updating. Will fix.
"Drop items, it's just enum"
Thanks,
Caleb
>
> It seems my or other reviewer's previous comments were not fully
> addressed. Maybe the feedback got lost between the quotes, maybe you
> just forgot to apply it. Please go back to the previous discussion and
> either implement all requested changes or keep discussing them.
>
> Thank you.
> </form letter>
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 1/8] dt-bindings: clock, reset: Add econet EN751221
2026-03-10 8:37 ` Caleb James DeLisle
@ 2026-03-10 8:51 ` Krzysztof Kozlowski
0 siblings, 0 replies; 23+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-10 8:51 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
On 10/03/2026 09:37, Caleb James DeLisle wrote:
>>> diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
>>> index a8471367175b..91abe7716fce 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
>> 751 < 752, keep alphanumeric order
>
>
> "econet," after "airoha," because e > a, of course I can order by number
> if that's really what you want.
Ah, yes, code is correct.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 2/8] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu
2026-03-09 13:18 [PATCH v2 0/8] mips: econet: Add clk/reset and PCIe support Caleb James DeLisle
2026-03-09 13:18 ` [PATCH v2 1/8] dt-bindings: clock, reset: Add econet EN751221 Caleb James DeLisle
@ 2026-03-09 13:18 ` Caleb James DeLisle
2026-03-11 14:39 ` Brian Masney
2026-03-09 13:18 ` [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528 Caleb James DeLisle
` (5 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-09 13:18 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
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 | 238 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 236 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..f7bd7034cf7f 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,49 @@
#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
+
+#define EN751221_MAX_CLKS 6
+
+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 +130,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 +339,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 +451,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 +703,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 +805,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 +814,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 +853,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) || key >= EN751221_MAX_CLKS)
+ 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 +1016,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
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH v2 2/8] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu
2026-03-09 13:18 ` [PATCH v2 2/8] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu Caleb James DeLisle
@ 2026-03-11 14:39 ` Brian Masney
2026-03-11 17:12 ` Caleb James DeLisle
0 siblings, 1 reply; 23+ messages in thread
From: Brian Masney @ 2026-03-11 14:39 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
Hi Caleb,
On Mon, Mar 09, 2026 at 01:18:12PM +0000, Caleb James DeLisle wrote:
> 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 | 238 ++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 236 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..f7bd7034cf7f 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,49 @@
> #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
> +
> +#define EN751221_MAX_CLKS 6
> +
> +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 +130,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 +339,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 +451,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 +703,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);
I assume the mix of en7523 and en7581 is ok here?
> }
>
> static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
> @@ -705,7 +805,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 +814,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 +853,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;
No space with the cast.
> +
> + 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) || key >= EN751221_MAX_CLKS)
> + pr_err("Failed to register clk %s: %pe\n", name, hw);
Is %pe correct in the case when key >= EN751221_MAX_CLKS?
> + else
> + clk_data->hws[key] = hw;
Should the error code be returned here? I know the function has try in
it's name, however if this fails, then it still registers it.
> +}
> +
> +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;
Should 40 be documented a little better with a #define?
> +
> + 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;
Should a warning be logged here or in get_hw_id() above? hid can be set
to HIR_UNKNOWN here.
> + }
> + 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);
Again, any reason why the error handling is missing here?
Brian
> +
> + 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 +1016,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
>
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH v2 2/8] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu
2026-03-11 14:39 ` Brian Masney
@ 2026-03-11 17:12 ` Caleb James DeLisle
2026-03-11 19:44 ` Brian Masney
0 siblings, 1 reply; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-11 17:12 UTC (permalink / raw)
To: Brian Masney
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
Hello Brian,
Thank you for taking the time!
On 11/03/2026 15:39, Brian Masney wrote:
> Hi Caleb,
>
> On Mon, Mar 09, 2026 at 01:18:12PM +0000, Caleb James DeLisle wrote:
>> 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 | 238 ++++++++++++++++++++++++++++++++++++++-
>> 2 files changed, 236 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..f7bd7034cf7f 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,49 @@
>> #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
>> +
>> +#define EN751221_MAX_CLKS 6
>> +
>> +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 +130,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 +339,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 +451,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 +703,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);
> I assume the mix of en7523 and en7581 is ok here?
Correct, en7581 came first, then when en7523 was added they reused the
function. I'm only changing the offsets to be passed in because en751221
has more reset registers so different offset table than the others.
>> }
>>
>> static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
>> @@ -705,7 +805,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 +814,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 +853,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;
> No space with the cast.
OK
>> +
>> + 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) || key >= EN751221_MAX_CLKS)
>> + pr_err("Failed to register clk %s: %pe\n", name, hw);
> Is %pe correct in the case when key >= EN751221_MAX_CLKS?
Hmm, it's gonna give a pointer address, indeed that's not so nice. I'll
re-work this so it makes more sense.
>> + else
>> + clk_data->hws[key] = hw;
> Should the error code be returned here? I know the function has try in
> it's name, however if this fails, then it still registers it.
This function follows the general pattern of en7581_register_clocks().
If a clock can't be registered, leave clk_data->hws[key] as NULL, log,
and continue. There's only two possible reasons for failing, if
clk_hw_register_fixed_rate() fails then it's not registered because it
failed. If key >= EN751221_MAX_CLKS, it does register but I'll fix this
so it's checking that before clk_hw_register_fixed_rate().
>> +}
>> +
>> +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;
> Should 40 be documented a little better with a #define?
Ok yes, makes sense.
>> +
>> + 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;
> Should a warning be logged here or in get_hw_id() above? hid can be set
> to HIR_UNKNOWN here.
Now that I'm looking at this again, I'm starting to think it might be
better to just remove it and use a fixed-clock in the DT. I wrote it
aiming for completeness, but this particular clock has so much code
supporting it, I'm feeling like it just doesn't make any sense.
Let me know if you have a feeling on this because I'm swaying in the
direction of just re-sending with it removed.
>
>> + }
>> + 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);
> Again, any reason why the error handling is missing here?
I followed the same logic that was used for the en7581 and en7523, but I
think the logic is reasonable. If a clock fails to register, you either
log and continue, or you blow up the whole probe(), which is just going
to make it more frustrating to debug since then no clocks will register
and anything downstream of them will be unhappy.
Thanks,
Caleb
>
> Brian
>
>
>> +
>> + 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 +1016,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
>>
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH v2 2/8] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu
2026-03-11 17:12 ` Caleb James DeLisle
@ 2026-03-11 19:44 ` Brian Masney
0 siblings, 0 replies; 23+ messages in thread
From: Brian Masney @ 2026-03-11 19:44 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
On Wed, Mar 11, 2026 at 06:12:59PM +0100, Caleb James DeLisle wrote:
> Hello Brian,
>
> Thank you for taking the time!
>
>
> On 11/03/2026 15:39, Brian Masney wrote:
> > Hi Caleb,
> >
> > On Mon, Mar 09, 2026 at 01:18:12PM +0000, Caleb James DeLisle wrote:
> > > 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>
> > > ---
> > > static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
> > > {
> > > @@ -604,7 +703,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);
> > I assume the mix of en7523 and en7581 is ok here?
>
>
> Correct, en7581 came first, then when en7523 was added they reused the
> function. I'm only changing the offsets to be passed in because en751221 has
> more reset registers so different offset table than the others.
Sounds good. I just wanted to confirm.
> > > + else
> > > + clk_data->hws[key] = hw;
> > Should the error code be returned here? I know the function has try in
> > it's name, however if this fails, then it still registers it.
>
>
> This function follows the general pattern of en7581_register_clocks(). If a
> clock can't be registered, leave clk_data->hws[key] as NULL, log, and
> continue. There's only two possible reasons for failing, if
> clk_hw_register_fixed_rate() fails then it's not registered because it
> failed. If key >= EN751221_MAX_CLKS, it does register but I'll fix this so
> it's checking that before clk_hw_register_fixed_rate().
I see that Stephen picked up this driver in 2022 with that behavior. I'm
fine with it if he is.
> > > + /* 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;
> > Should a warning be logged here or in get_hw_id() above? hid can be set
> > to HIR_UNKNOWN here.
>
> Now that I'm looking at this again, I'm starting to think it might be better
> to just remove it and use a fixed-clock in the DT. I wrote it aiming for
> completeness, but this particular clock has so much code supporting it, I'm
> feeling like it just doesn't make any sense.
>
> Let me know if you have a feeling on this because I'm swaying in the
> direction of just re-sending with it removed.
That makes sense to me.
Brian
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528
2026-03-09 13:18 [PATCH v2 0/8] mips: econet: Add clk/reset and PCIe support Caleb James DeLisle
2026-03-09 13:18 ` [PATCH v2 1/8] dt-bindings: clock, reset: Add econet EN751221 Caleb James DeLisle
2026-03-09 13:18 ` [PATCH v2 2/8] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu Caleb James DeLisle
@ 2026-03-09 13:18 ` Caleb James DeLisle
2026-03-10 8:24 ` Krzysztof Kozlowski
2026-03-09 13:18 ` [PATCH v2 4/8] phy: econet: Add PCIe PHY driver for EcoNet EN751221 and EN7528 SoCs Caleb James DeLisle
` (4 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-09 13:18 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
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 | 50 +++++++++++++++++++
MAINTAINERS | 6 +++
2 files changed, 56 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..987d396c1c64
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml
@@ -0,0 +1,50 @@
+# 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-gen1
+ - econet,en751221-pcie-gen2
+ - econet,en7528-pcie-gen1
+ - econet,en7528-pcie-gen2
+
+ reg:
+ maxItems: 1
+
+ "#phy-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pcie-phy@1faf2000 {
+ compatible = "econet,en7528-pcie-gen1";
+ reg = <0x1faf2000 0x1000>;
+ #phy-cells = <0>;
+ };
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 3781d55db5bb..bc925fa08baa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9122,6 +9122,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
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528
2026-03-09 13:18 ` [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528 Caleb James DeLisle
@ 2026-03-10 8:24 ` Krzysztof Kozlowski
2026-03-10 10:37 ` Caleb James DeLisle
0 siblings, 1 reply; 23+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-10 8:24 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
On Mon, Mar 09, 2026 at 01:18:13PM +0000, Caleb James DeLisle wrote:
> 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>
Still, four separate subsystems unnecessarily merged into one patchset.
Split independent parts of your work per subsystem. See also submitting
patches.
> ---
> .../phy/econet,en751221-pcie-phy.yaml | 50 +++++++++++++++++++
> MAINTAINERS | 6 +++
> 2 files changed, 56 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528
2026-03-10 8:24 ` Krzysztof Kozlowski
@ 2026-03-10 10:37 ` Caleb James DeLisle
2026-03-10 10:40 ` Krzysztof Kozlowski
0 siblings, 1 reply; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-10 10:37 UTC (permalink / raw)
To: Krzysztof Kozlowski
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
On 10/03/2026 09:24, Krzysztof Kozlowski wrote:
> On Mon, Mar 09, 2026 at 01:18:13PM +0000, Caleb James DeLisle wrote:
>> 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>
> Still, four separate subsystems unnecessarily merged into one patchset.
> Split independent parts of your work per subsystem. See also submitting
> patches.
I asked for clarification last time and didn't get a reply. I'm not
against changing it but need to understand exactly what's expected b/c
the way I'm imagining it seems way worse. submitting-patches.rst only
says of patch sets "only post say 15 or so at a time", obviously not the
case here.
If you're asking for one patchset for phy, one for clock, one for PCI,
and then one to introduce them to the device, I can do that. I just want
to be sure because introducing unused code, and patch sets that depend
on other patch sets both seem like anti-patterns to me.
Thanks,
Caleb
>> ---
>> .../phy/econet,en751221-pcie-phy.yaml | 50 +++++++++++++++++++
>> MAINTAINERS | 6 +++
>> 2 files changed, 56 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/phy/econet,en751221-pcie-phy.yaml
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
>
> Best regards,
> Krzysztof
>
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528
2026-03-10 10:37 ` Caleb James DeLisle
@ 2026-03-10 10:40 ` Krzysztof Kozlowski
2026-03-10 10:40 ` Krzysztof Kozlowski
2026-03-10 11:13 ` Caleb James DeLisle
0 siblings, 2 replies; 23+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-10 10:40 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
On 10/03/2026 11:37, Caleb James DeLisle wrote:
>
> On 10/03/2026 09:24, Krzysztof Kozlowski wrote:
>> On Mon, Mar 09, 2026 at 01:18:13PM +0000, Caleb James DeLisle wrote:
>>> 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>
>> Still, four separate subsystems unnecessarily merged into one patchset.
>> Split independent parts of your work per subsystem. See also submitting
>> patches.
>
>
> I asked for clarification last time and didn't get a reply. I'm not
> against changing it but need to understand exactly what's expected b/c
> the way I'm imagining it seems way worse. submitting-patches.rst only
> says of patch sets "only post say 15 or so at a time", obviously not the
> case here.
>
> If you're asking for one patchset for phy, one for clock, one for PCI,
> and then one to introduce them to the device, I can do that. I just want
> to be sure because introducing unused code, and patch sets that depend
What is "unused" code? Or how is it unused? Do you understand this will
go via different subsystems and nothing will be "used" anyway?
> on other patch sets both seem like anti-patterns to me.
And asking four different maintainers to manually pick up individual
bits with multiple commands, instead of just applying entire set
targeting their subsystem, is pro-pattern here? No. Why adding more work
to maintainers?
Think how this is seen by individual subsystem maintainers and how they
should handle it.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528
2026-03-10 10:40 ` Krzysztof Kozlowski
@ 2026-03-10 10:40 ` Krzysztof Kozlowski
2026-03-10 11:13 ` Caleb James DeLisle
1 sibling, 0 replies; 23+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-10 10:40 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
On 10/03/2026 11:40, Krzysztof Kozlowski wrote:
> On 10/03/2026 11:37, Caleb James DeLisle wrote:
>>
>> On 10/03/2026 09:24, Krzysztof Kozlowski wrote:
>>> On Mon, Mar 09, 2026 at 01:18:13PM +0000, Caleb James DeLisle wrote:
>>>> 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>
>>> Still, four separate subsystems unnecessarily merged into one patchset.
>>> Split independent parts of your work per subsystem. See also submitting
>>> patches.
>>
>>
>> I asked for clarification last time and didn't get a reply. I'm not
>> against changing it but need to understand exactly what's expected b/c
>> the way I'm imagining it seems way worse. submitting-patches.rst only
>> says of patch sets "only post say 15 or so at a time", obviously not the
>> case here.
>>
>> If you're asking for one patchset for phy, one for clock, one for PCI,
>> and then one to introduce them to the device, I can do that. I just want
>> to be sure because introducing unused code, and patch sets that depend
>
> What is "unused" code? Or how is it unused? Do you understand this will
> go via different subsystems and nothing will be "used" anyway?
>
>> on other patch sets both seem like anti-patterns to me.
>
> And asking four different maintainers to manually pick up individual
> bits with multiple commands, instead of just applying entire set
> targeting their subsystem, is pro-pattern here? No. Why adding more work
> to maintainers?
>
> Think how this is seen by individual subsystem maintainers and how they
> should handle it.
>
Heh, and nothing of this is explained in cover letter - nothing about
dependencies or merging order - so how anyone can figure out what can be
applied here?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528
2026-03-10 10:40 ` Krzysztof Kozlowski
2026-03-10 10:40 ` Krzysztof Kozlowski
@ 2026-03-10 11:13 ` Caleb James DeLisle
2026-03-10 11:20 ` Krzysztof Kozlowski
1 sibling, 1 reply; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-10 11:13 UTC (permalink / raw)
To: Krzysztof Kozlowski
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
On 10/03/2026 11:40, Krzysztof Kozlowski wrote:
> On 10/03/2026 11:37, Caleb James DeLisle wrote:
>> On 10/03/2026 09:24, Krzysztof Kozlowski wrote:
>>> On Mon, Mar 09, 2026 at 01:18:13PM +0000, Caleb James DeLisle wrote:
>>>> 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>
>>> Still, four separate subsystems unnecessarily merged into one patchset.
>>> Split independent parts of your work per subsystem. See also submitting
>>> patches.
>>
>> I asked for clarification last time and didn't get a reply. I'm not
>> against changing it but need to understand exactly what's expected b/c
>> the way I'm imagining it seems way worse. submitting-patches.rst only
>> says of patch sets "only post say 15 or so at a time", obviously not the
>> case here.
>>
>> If you're asking for one patchset for phy, one for clock, one for PCI,
>> and then one to introduce them to the device, I can do that. I just want
>> to be sure because introducing unused code, and patch sets that depend
> What is "unused" code? Or how is it unused? Do you understand this will
> go via different subsystems and nothing will be "used" anyway?
Unused in the sense that you can't exercise that code without additional
code which is out of tree - at least until the subsequent patch set lands.
>> on other patch sets both seem like anti-patterns to me.
> And asking four different maintainers to manually pick up individual
> bits with multiple commands, instead of just applying entire set
> targeting their subsystem, is pro-pattern here? No. Why adding more work
> to maintainers?
>
> Think how this is seen by individual subsystem maintainers and how they
> should handle it.
Okay I think I see the goal, thank you. And you know I'm not smart
enough to have an actual opinion on this, I just needed to understand
the "why" so that I can do what's expected w/o goofing it up.
Thanks,
Caleb
>
>
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528
2026-03-10 11:13 ` Caleb James DeLisle
@ 2026-03-10 11:20 ` Krzysztof Kozlowski
0 siblings, 0 replies; 23+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-10 11:20 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
On 10/03/2026 12:13, Caleb James DeLisle wrote:
>
> On 10/03/2026 11:40, Krzysztof Kozlowski wrote:
>> On 10/03/2026 11:37, Caleb James DeLisle wrote:
>>> On 10/03/2026 09:24, Krzysztof Kozlowski wrote:
>>>> On Mon, Mar 09, 2026 at 01:18:13PM +0000, Caleb James DeLisle wrote:
>>>>> 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>
>>>> Still, four separate subsystems unnecessarily merged into one patchset.
>>>> Split independent parts of your work per subsystem. See also submitting
>>>> patches.
>>>
>>> I asked for clarification last time and didn't get a reply. I'm not
>>> against changing it but need to understand exactly what's expected b/c
>>> the way I'm imagining it seems way worse. submitting-patches.rst only
>>> says of patch sets "only post say 15 or so at a time", obviously not the
>>> case here.
>>>
>>> If you're asking for one patchset for phy, one for clock, one for PCI,
>>> and then one to introduce them to the device, I can do that. I just want
>>> to be sure because introducing unused code, and patch sets that depend
>> What is "unused" code? Or how is it unused? Do you understand this will
>> go via different subsystems and nothing will be "used" anyway?
>
>
> Unused in the sense that you can't exercise that code without additional
> code which is out of tree - at least until the subsequent patch set lands.
Which is exactly the same as with your method of combining independent
subsystems here. Do you know this goes via independent subsystems?
Around four of them?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 4/8] phy: econet: Add PCIe PHY driver for EcoNet EN751221 and EN7528 SoCs.
2026-03-09 13:18 [PATCH v2 0/8] mips: econet: Add clk/reset and PCIe support Caleb James DeLisle
` (2 preceding siblings ...)
2026-03-09 13:18 ` [PATCH v2 3/8] dt-bindings: phy: Document PCIe PHY in EcoNet EN751221 and EN7528 Caleb James DeLisle
@ 2026-03-09 13:18 ` Caleb James DeLisle
2026-03-09 13:18 ` [PATCH v2 5/8] dt-bindings: PCI: mediatek: Add support for EcoNet EN7528 Caleb James DeLisle
` (3 subsequent siblings)
7 siblings, 0 replies; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-09 13:18 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
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]
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 bc925fa08baa..e61a349864fc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9127,6 +9127,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..d2c6e0c1f331
--- /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_gen1[] = {
+ {
+ .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_gen2[] = {
+ {
+ .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_gen2[] = {
+ {
+ .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, ®map_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-gen1", .data = en7528_phy_gen1 },
+ { .compatible = "econet,en7528-pcie-gen2", .data = en7528_phy_gen2 },
+ { .compatible = "econet,en751221-pcie-gen1", .data = en7528_phy_gen1 },
+ { .compatible = "econet,en751221-pcie-gen2", .data = en751221_phy_gen2 },
+ { /* 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
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH v2 5/8] dt-bindings: PCI: mediatek: Add support for EcoNet EN7528
2026-03-09 13:18 [PATCH v2 0/8] mips: econet: Add clk/reset and PCIe support Caleb James DeLisle
` (3 preceding siblings ...)
2026-03-09 13:18 ` [PATCH v2 4/8] phy: econet: Add PCIe PHY driver for EcoNet EN751221 and EN7528 SoCs Caleb James DeLisle
@ 2026-03-09 13:18 ` Caleb James DeLisle
2026-03-10 8:25 ` Krzysztof Kozlowski
2026-03-09 13:18 ` [PATCH v2 6/8] PCI: mediatek: Add support for EcoNet EN7528 SoC Caleb James DeLisle
` (2 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-09 13:18 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
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
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH v2 5/8] dt-bindings: PCI: mediatek: Add support for EcoNet EN7528
2026-03-09 13:18 ` [PATCH v2 5/8] dt-bindings: PCI: mediatek: Add support for EcoNet EN7528 Caleb James DeLisle
@ 2026-03-10 8:25 ` Krzysztof Kozlowski
2026-03-10 8:49 ` Caleb James DeLisle
0 siblings, 1 reply; 23+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-10 8:25 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
On Mon, Mar 09, 2026 at 01:18:15PM +0000, Caleb James DeLisle wrote:
> 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
Patch is heavily incomplete - why do you have variable number of clocks?
1, 2, 3 ... or 6 at the same time?
Look at the rest of this file to understand what you need to write.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 5/8] dt-bindings: PCI: mediatek: Add support for EcoNet EN7528
2026-03-10 8:25 ` Krzysztof Kozlowski
@ 2026-03-10 8:49 ` Caleb James DeLisle
0 siblings, 0 replies; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-10 8:49 UTC (permalink / raw)
To: Krzysztof Kozlowski
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
On 10/03/2026 09:25, Krzysztof Kozlowski wrote:
> On Mon, Mar 09, 2026 at 01:18:15PM +0000, Caleb James DeLisle wrote:
>> 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
> Patch is heavily incomplete - why do you have variable number of clocks?
> 1, 2, 3 ... or 6 at the same time?
>
> Look at the rest of this file to understand what you need to write.
Thank you, sorry for missing that, will fix.
Caleb
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 6/8] PCI: mediatek: Add support for EcoNet EN7528 SoC
2026-03-09 13:18 [PATCH v2 0/8] mips: econet: Add clk/reset and PCIe support Caleb James DeLisle
` (4 preceding siblings ...)
2026-03-09 13:18 ` [PATCH v2 5/8] dt-bindings: PCI: mediatek: Add support for EcoNet EN7528 Caleb James DeLisle
@ 2026-03-09 13:18 ` Caleb James DeLisle
2026-03-09 13:18 ` [PATCH v2 7/8] PCI: Skip bridge window reads when window is not supported Caleb James DeLisle
2026-03-09 13:18 ` [PATCH v2 8/8] mips: dts: Add PCIe to EcoNet EN751221 Caleb James DeLisle
7 siblings, 0 replies; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-09 13:18 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 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.
Co-developed-by: Ahmed Naseef <naseefkm@gmail.com>
Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
drivers/pci/controller/Kconfig | 2 +-
drivers/pci/controller/pcie-mediatek.c | 118 +++++++++++++++++++++++++
2 files changed, 119 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..84064061652a 100644
--- a/drivers/pci/controller/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
@@ -14,6 +14,7 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/irqchip/irq-msi-lib.h>
#include <linux/irqdomain.h>
+#include <linux/kconfig.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/msi.h>
@@ -77,6 +78,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 +91,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 +760,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 +1236,30 @@ 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))) {
+ int ret = -EOPNOTSUPP;
+
+ if (rc->bus != bus)
+ continue;
+
+ #if IS_BUILTIN(CONFIG_PCIE_MEDIATEK)
+ ret = pcie_retrain_link(rc, true);
+ #endif
+
+ if (!ret)
+ dev_info(dev, "port%d link retrained\n",
+ PCI_SLOT(rc->devfn));
+ else
+ dev_info(dev, "port%d failed to retrain %pe\n",
+ PCI_SLOT(rc->devfn), ERR_PTR(ret));
+ }
+ }
+
return 0;
put_resources:
@@ -1264,8 +1375,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
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH v2 7/8] PCI: Skip bridge window reads when window is not supported
2026-03-09 13:18 [PATCH v2 0/8] mips: econet: Add clk/reset and PCIe support Caleb James DeLisle
` (5 preceding siblings ...)
2026-03-09 13:18 ` [PATCH v2 6/8] PCI: mediatek: Add support for EcoNet EN7528 SoC Caleb James DeLisle
@ 2026-03-09 13:18 ` Caleb James DeLisle
2026-03-09 13:18 ` [PATCH v2 8/8] mips: dts: Add PCIe to EcoNet EN751221 Caleb James DeLisle
7 siblings, 0 replies; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-09 13:18 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
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>
Link: https://lore.kernel.org/all/20260113210259.GA715789@bhelgaas/
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
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH v2 8/8] mips: dts: Add PCIe to EcoNet EN751221
2026-03-09 13:18 [PATCH v2 0/8] mips: econet: Add clk/reset and PCIe support Caleb James DeLisle
` (6 preceding siblings ...)
2026-03-09 13:18 ` [PATCH v2 7/8] PCI: Skip bridge window reads when window is not supported Caleb James DeLisle
@ 2026-03-09 13:18 ` Caleb James DeLisle
7 siblings, 0 replies; 23+ messages in thread
From: Caleb James DeLisle @ 2026-03-09 13:18 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 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..72cb65654c34 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-gen2";
+ reg = <0x1fac0000 0x1000>;
+ #phy-cells = <0>;
+ };
+
+ pcie_phy0: pcie-phy@1faf2000 {
+ compatible = "econet,en751221-pcie-gen1";
+ reg = <0x1faf2000 0x1000>;
+ #phy-cells = <0>;
+ };
+
+ scuclk: clock-controller@1fb00000 {
+ compatible = "econet,en751221-scu";
+ 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
^ permalink raw reply related [flat|nested] 23+ messages in thread