// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <dt-bindings/reset/econet,en751221-scu.h>
+
/dts-v1/;
/ {
};
};
+ chip_scu: syscon@1fa20000 {
+ compatible = "econet,en751221-chip-scu", "syscon";
+ reg = <0x1fa20000 0x388>;
+ };
+
intc: interrupt-controller@1fb40000 {
compatible = "econet,en751221-intc";
reg = <0x1fb40000 0x100>;
econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>;
};
+ scuclk: clock-controller@1fb00000 {
+ compatible = "econet,en751221-scu", "syscon";
+ reg = <0x1fb00000 0x970>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
ethernet: ethernet@1fb50000 {
compatible = "econet,en751221-eth";
reg = <0x1fb50000 0x10000>;
+ resets = <&scuclk EN751221_FE_RST>,
+ <&scuclk EN751221_FE_QDMA1_RST>,
+ <&scuclk EN751221_FE_QDMA2_RST>,
+ <&scuclk EN751221_GSW_RST>,
+ <&scuclk EN751221_XPON_MAC_RST>,
+ <&scuclk EN751221_XPON_PHY_RST>;
+ reset-names = "fe", "qdma0", "qdma1", "gsw",
+ "xpon-mac", "xpon-phy";
+
#address-cells = <1>;
#size-cells = <0>;
CONFIG_CLKSRC_MMIO=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_COMMON_CLK=y
+CONFIG_COMMON_CLK_EN7523=y
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CONTEXT_TRACKING=y
CONFIG_QUEUED_SPINLOCKS=y
CONFIG_RANDSTRUCT_NONE=y
CONFIG_RATIONAL=y
+CONFIG_RESET_CONTROLLER=y
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES=y
--- /dev/null
+From 82e6bf912d5846646892becea659b39d178d79e3 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Tue, 12 Nov 2024 01:08:53 +0100
+Subject: [PATCH 5/8] clk: en7523: move en7581_reset_register() in
+ en7581_clk_hw_init()
+
+Move en7581_reset_register routine in en7581_clk_hw_init() since reset
+feature is supported just by EN7581 SoC.
+Get rid of reset struct in en_clk_soc_data data struct.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-6-8ada5e394ae4@kernel.org
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/clk-en7523.c | 93 ++++++++++++++--------------------------
+ 1 file changed, 33 insertions(+), 60 deletions(-)
+
+diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
+index fdd8ea989ed2..60dc938144d7 100644
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -76,11 +76,6 @@ struct en_rst_data {
+
+ struct en_clk_soc_data {
+ const struct clk_ops pcie_ops;
+- struct {
+- const u16 *bank_ofs;
+- const u16 *idx_map;
+- u16 idx_map_nr;
+- } reset;
+ int (*hw_init)(struct platform_device *pdev,
+ struct clk_hw_onecell_data *clk_data);
+ };
+@@ -595,32 +590,6 @@ static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_dat
+ clk_data->num = EN7523_NUM_CLOCKS;
+ }
+
+-static int en7581_clk_hw_init(struct platform_device *pdev,
+- struct clk_hw_onecell_data *clk_data)
+-{
+- void __iomem *np_base;
+- struct regmap *map;
+- u32 val;
+-
+- map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
+- if (IS_ERR(map))
+- return PTR_ERR(map);
+-
+- np_base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(np_base))
+- return PTR_ERR(np_base);
+-
+- en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
+-
+- val = readl(np_base + REG_NP_SCU_SSTR);
+- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
+- writel(val, np_base + REG_NP_SCU_SSTR);
+- val = readl(np_base + REG_NP_SCU_PCIC);
+- writel(val | 3, np_base + REG_NP_SCU_PCIC);
+-
+- return 0;
+-}
+-
+ static int en7523_reset_update(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+ {
+@@ -670,23 +639,18 @@ static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
+ return rst_data->idx_map[reset_spec->args[0]];
+ }
+
+-static const struct reset_control_ops en7523_reset_ops = {
++static const struct reset_control_ops en7581_reset_ops = {
+ .assert = en7523_reset_assert,
+ .deassert = en7523_reset_deassert,
+ .status = en7523_reset_status,
+ };
+
+-static int en7523_reset_register(struct platform_device *pdev,
+- const struct en_clk_soc_data *soc_data)
++static int en7581_reset_register(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct en_rst_data *rst_data;
+ void __iomem *base;
+
+- /* no reset lines available */
+- if (!soc_data->reset.idx_map_nr)
+- return 0;
+-
+ base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+@@ -695,13 +659,13 @@ static int en7523_reset_register(struct platform_device *pdev,
+ if (!rst_data)
+ return -ENOMEM;
+
+- rst_data->bank_ofs = soc_data->reset.bank_ofs;
+- rst_data->idx_map = soc_data->reset.idx_map;
++ rst_data->bank_ofs = en7581_rst_ofs;
++ rst_data->idx_map = en7581_rst_map;
+ rst_data->base = base;
+
+- rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr;
++ rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
+ rst_data->rcdev.of_xlate = en7523_reset_xlate;
+- rst_data->rcdev.ops = &en7523_reset_ops;
++ rst_data->rcdev.ops = &en7581_reset_ops;
+ rst_data->rcdev.of_node = dev->of_node;
+ rst_data->rcdev.of_reset_n_cells = 1;
+ rst_data->rcdev.owner = THIS_MODULE;
+@@ -710,6 +674,32 @@ static int en7523_reset_register(struct platform_device *pdev,
+ return devm_reset_controller_register(dev, &rst_data->rcdev);
+ }
+
++static int en7581_clk_hw_init(struct platform_device *pdev,
++ struct clk_hw_onecell_data *clk_data)
++{
++ void __iomem *np_base;
++ struct regmap *map;
++ u32 val;
++
++ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
++ if (IS_ERR(map))
++ return PTR_ERR(map);
++
++ np_base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(np_base))
++ return PTR_ERR(np_base);
++
++ en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
++
++ val = readl(np_base + REG_NP_SCU_SSTR);
++ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
++ writel(val, np_base + REG_NP_SCU_SSTR);
++ val = readl(np_base + REG_NP_SCU_PCIC);
++ writel(val | 3, np_base + REG_NP_SCU_PCIC);
++
++ return en7581_reset_register(pdev);
++}
++
+ static int en7523_clk_probe(struct platform_device *pdev)
+ {
+ struct device_node *node = pdev->dev.of_node;
+@@ -728,19 +718,7 @@ static int en7523_clk_probe(struct platform_device *pdev)
+ if (r)
+ return r;
+
+- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+- if (r)
+- return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n",
+- pdev->name);
+-
+- r = en7523_reset_register(pdev, soc_data);
+- if (r) {
+- of_clk_del_provider(node);
+- return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n",
+- pdev->name);
+- }
+-
+- return 0;
++ return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+ }
+
+ static const struct en_clk_soc_data en7523_data = {
+@@ -758,11 +736,6 @@ static const struct en_clk_soc_data en7581_data = {
+ .enable = en7581_pci_enable,
+ .disable = en7581_pci_disable,
+ },
+- .reset = {
+- .bank_ofs = en7581_rst_ofs,
+- .idx_map = en7581_rst_map,
+- .idx_map_nr = ARRAY_SIZE(en7581_rst_map),
+- },
+ .hw_init = en7581_clk_hw_init,
+ };
+
+--
+2.39.5
+
--- /dev/null
+From a9eaf305017a5ebe73ab34e85bd5414055a88f29 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Tue, 12 Nov 2024 01:08:54 +0100
+Subject: [PATCH 6/8] clk: en7523: map io region in a single block
+
+Map all clock-controller memory region in a single block.
+This patch does not introduce any backward incompatibility since the dts
+for EN7581 SoC is not upstream yet.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-7-8ada5e394ae4@kernel.org
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/clk-en7523.c | 32 +++++++++++++-------------------
+ 1 file changed, 13 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
+index 60dc938144d7..e52c5460e927 100644
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -39,8 +39,8 @@
+ #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
+ #define REG_CRYPTO_CLKSRC2 0x20c
+
+-#define REG_RST_CTRL2 0x00
+-#define REG_RST_CTRL1 0x04
++#define REG_RST_CTRL2 0x830
++#define REG_RST_CTRL1 0x834
+
+ struct en_clk_desc {
+ int id;
+@@ -645,15 +645,9 @@ static const struct reset_control_ops en7581_reset_ops = {
+ .status = en7523_reset_status,
+ };
+
+-static int en7581_reset_register(struct platform_device *pdev)
++static int en7581_reset_register(struct device *dev, void __iomem *base)
+ {
+- struct device *dev = &pdev->dev;
+ struct en_rst_data *rst_data;
+- void __iomem *base;
+-
+- base = devm_platform_ioremap_resource(pdev, 1);
+- if (IS_ERR(base))
+- return PTR_ERR(base);
+
+ rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
+ if (!rst_data)
+@@ -677,27 +671,27 @@ static int en7581_reset_register(struct platform_device *pdev)
+ static int en7581_clk_hw_init(struct platform_device *pdev,
+ struct clk_hw_onecell_data *clk_data)
+ {
+- void __iomem *np_base;
+ struct regmap *map;
++ void __iomem *base;
+ u32 val;
+
+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+- np_base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(np_base))
+- return PTR_ERR(np_base);
++ base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
+
+- en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
++ en7581_register_clocks(&pdev->dev, clk_data, map, base);
+
+- val = readl(np_base + REG_NP_SCU_SSTR);
++ val = readl(base + REG_NP_SCU_SSTR);
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
+- writel(val, np_base + REG_NP_SCU_SSTR);
+- val = readl(np_base + REG_NP_SCU_PCIC);
+- writel(val | 3, np_base + REG_NP_SCU_PCIC);
++ writel(val, base + REG_NP_SCU_SSTR);
++ val = readl(base + REG_NP_SCU_PCIC);
++ writel(val | 3, base + REG_NP_SCU_PCIC);
+
+- return en7581_reset_register(pdev);
++ return en7581_reset_register(&pdev->dev, base);
+ }
+
+ static int en7523_clk_probe(struct platform_device *pdev)
+--
+2.39.5
+
--- /dev/null
+From 90d4e466c9ea2010f33880a36317a8486ccbe082 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Wed, 8 Jan 2025 10:50:43 +0100
+Subject: [PATCH 1/3] PCI: mediatek-gen3: Move reset delay in
+ mtk_pcie_en7581_power_up()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal
+causing occasional PCIe link down issues. In order to overcome the
+problem, PCIe block is reset using REG_PCI_CONTROL (0x88) and
+REG_RESET_CONTROL (0x834) registers available in the clock module
+running clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up().
+
+In order to make the code more readable, move the wait for the time
+needed to complete the PCIe reset from en7581_pci_enable() to
+mtk_pcie_en7581_power_up().
+
+Reduce reset timeout from 250ms to the standard PCIE_T_PVPERL_MS value
+(100ms) since it has no impact on the driver behavior.
+
+Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-4-21ac939a3b9b@kernel.org
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Acked-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/clk-en7523.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
+index e52c5460e927..513730e5b953 100644
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -477,7 +477,6 @@ static int en7581_pci_enable(struct clk_hw *hw)
+ REG_PCI_CONTROL_PERSTOUT;
+ val = readl(np_base + REG_PCI_CONTROL);
+ writel(val | mask, np_base + REG_PCI_CONTROL);
+- msleep(250);
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From e4a9748e7103c47e575459db2b6a77d14f34da2b Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 14 Jan 2025 00:10:02 +0100
+Subject: [PATCH 2/3] clk: en7523: Rework clock handling for different clock
+ numbers
+
+Airoha EN7581 SoC have additional clock compared to EN7523 but current
+driver permits to only support up to EN7523 clock numbers.
+
+To handle this, rework the clock handling and permit to declare the
+clocks number in match_data and alloca clk_data based on the compatible
+match_data.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Link: https://lore.kernel.org/r/20250113231030.6735-2-ansuelsmth@gmail.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/clk-en7523.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
+index 495c0d607c7d..3a4b7ed40af4 100644
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -75,6 +75,7 @@ struct en_rst_data {
+ };
+
+ struct en_clk_soc_data {
++ u32 num_clocks;
+ const struct clk_ops pcie_ops;
+ int (*hw_init)(struct platform_device *pdev,
+ struct clk_hw_onecell_data *clk_data);
+@@ -504,8 +505,6 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
+ u32 rate;
+ int i;
+
+- clk_data->num = EN7523_NUM_CLOCKS;
+-
+ for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
+ const struct en_clk_desc *desc = &en7523_base_clks[i];
+ u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
+@@ -587,8 +586,6 @@ static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_dat
+
+ hw = en7523_register_pcie_clk(dev, base);
+ clk_data->hws[EN7523_CLK_PCIE] = hw;
+-
+- clk_data->num = EN7523_NUM_CLOCKS;
+ }
+
+ static int en7523_reset_update(struct reset_controller_dev *rcdev,
+@@ -702,13 +699,15 @@ static int en7523_clk_probe(struct platform_device *pdev)
+ struct clk_hw_onecell_data *clk_data;
+ int r;
+
++ soc_data = device_get_match_data(&pdev->dev);
++
+ clk_data = devm_kzalloc(&pdev->dev,
+- struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
++ struct_size(clk_data, hws, soc_data->num_clocks),
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+- soc_data = device_get_match_data(&pdev->dev);
++ clk_data->num = soc_data->num_clocks;
+ r = soc_data->hw_init(pdev, clk_data);
+ if (r)
+ return r;
+@@ -717,6 +716,7 @@ static int en7523_clk_probe(struct platform_device *pdev)
+ }
+
+ static const struct en_clk_soc_data en7523_data = {
++ .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1,
+ .pcie_ops = {
+ .is_enabled = en7523_pci_is_enabled,
+ .prepare = en7523_pci_prepare,
+@@ -726,6 +726,8 @@ static const struct en_clk_soc_data en7523_data = {
+ };
+
+ static const struct en_clk_soc_data en7581_data = {
++ /* We increment num_clocks by 1 to account for additional PCIe clock */
++ .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1,
+ .pcie_ops = {
+ .is_enabled = en7581_pci_is_enabled,
+ .enable = en7581_pci_enable,
+--
+2.39.5
+
--- /dev/null
+From bfe257f9780d8f77045a7da6ec959ee0659d2f98 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 14 Jan 2025 00:10:05 +0100
+Subject: [PATCH 3/3] clk: en7523: Add clock for eMMC for EN7581
+
+Add clock for eMMC for EN7581. This is used to give info of the current
+eMMC source clock and to switch it from 200MHz or 150MHz.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Link: https://lore.kernel.org/r/20250113231030.6735-5-ansuelsmth@gmail.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/clk-en7523.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
+index 3a4b7ed40af4..6a763bc9ac1a 100644
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -91,6 +91,7 @@ static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 }
+ 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 };
+
+ static const struct en_clk_desc en7523_base_clks[] = {
+ {
+@@ -281,6 +282,15 @@ static const struct en_clk_desc en7581_base_clks[] = {
+ .base_shift = 0,
+ .base_values = crypto_base,
+ .n_base_values = ARRAY_SIZE(crypto_base),
++ }, {
++ .id = EN7581_CLK_EMMC,
++ .name = "emmc",
++
++ .base_reg = REG_CRYPTO_CLKSRC2,
++ .base_bits = 1,
++ .base_shift = 12,
++ .base_values = emmc7581_base,
++ .n_base_values = ARRAY_SIZE(emmc7581_base),
+ }
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 1c0608d860db973ad09b5a9ccb19b76ae07622a3 Mon Sep 17 00:00:00 2001
+From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
+Date: Mon, 10 Nov 2025 06:56:44 +0300
+Subject: [PATCH] clk: en7523: Add reset-controller support for EN7523 SoC
+
+Introduce reset API support to EN7523 clock driver. EN7523 uses the
+same reset logic as EN7581, so just reuse existing code.
+
+Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/clk-en7523.c | 64 ++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 59 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
+index 15bbdeb60b8e..08cc8e5acf43 100644
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -9,6 +9,7 @@
+ #include <linux/regmap.h>
+ #include <linux/reset-controller.h>
+ #include <dt-bindings/clock/en7523-clk.h>
++#include <dt-bindings/reset/airoha,en7523-reset.h>
+ #include <dt-bindings/reset/airoha,en7581-reset.h>
+
+ #define RST_NR_PER_BANK 32
+@@ -299,6 +300,53 @@ static const u16 en7581_rst_ofs[] = {
+ REG_RST_CTRL1,
+ };
+
++static const u16 en7523_rst_map[] = {
++ /* RST_CTRL2 */
++ [EN7523_XPON_PHY_RST] = 0,
++ [EN7523_XSI_MAC_RST] = 7,
++ [EN7523_XSI_PHY_RST] = 8,
++ [EN7523_NPU_RST] = 9,
++ [EN7523_I2S_RST] = 10,
++ [EN7523_TRNG_RST] = 11,
++ [EN7523_TRNG_MSTART_RST] = 12,
++ [EN7523_DUAL_HSI0_RST] = 13,
++ [EN7523_DUAL_HSI1_RST] = 14,
++ [EN7523_HSI_RST] = 15,
++ [EN7523_DUAL_HSI0_MAC_RST] = 16,
++ [EN7523_DUAL_HSI1_MAC_RST] = 17,
++ [EN7523_HSI_MAC_RST] = 18,
++ [EN7523_WDMA_RST] = 19,
++ [EN7523_WOE0_RST] = 20,
++ [EN7523_WOE1_RST] = 21,
++ [EN7523_HSDMA_RST] = 22,
++ [EN7523_I2C2RBUS_RST] = 23,
++ [EN7523_TDMA_RST] = 24,
++ /* RST_CTRL1 */
++ [EN7523_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0,
++ [EN7523_FE_PDMA_RST] = RST_NR_PER_BANK + 1,
++ [EN7523_FE_QDMA_RST] = RST_NR_PER_BANK + 2,
++ [EN7523_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4,
++ [EN7523_CRYPTO_RST] = RST_NR_PER_BANK + 6,
++ [EN7523_TIMER_RST] = RST_NR_PER_BANK + 8,
++ [EN7523_PCM1_RST] = RST_NR_PER_BANK + 11,
++ [EN7523_UART_RST] = RST_NR_PER_BANK + 12,
++ [EN7523_GPIO_RST] = RST_NR_PER_BANK + 13,
++ [EN7523_GDMA_RST] = RST_NR_PER_BANK + 14,
++ [EN7523_I2C_MASTER_RST] = RST_NR_PER_BANK + 16,
++ [EN7523_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17,
++ [EN7523_SFC_RST] = RST_NR_PER_BANK + 18,
++ [EN7523_UART2_RST] = RST_NR_PER_BANK + 19,
++ [EN7523_GDMP_RST] = RST_NR_PER_BANK + 20,
++ [EN7523_FE_RST] = RST_NR_PER_BANK + 21,
++ [EN7523_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22,
++ [EN7523_GSW_RST] = RST_NR_PER_BANK + 23,
++ [EN7523_SFC2_PCM_RST] = RST_NR_PER_BANK + 25,
++ [EN7523_PCIE0_RST] = RST_NR_PER_BANK + 26,
++ [EN7523_PCIE1_RST] = RST_NR_PER_BANK + 27,
++ [EN7523_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
++ [EN7523_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
++};
++
+ static const u16 en7581_rst_map[] = {
+ /* RST_CTRL2 */
+ [EN7581_XPON_PHY_RST] = 0,
+@@ -357,6 +405,9 @@ static const u16 en7581_rst_map[] = {
+ [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
+ };
+
++static int en7581_reset_register(struct device *dev, void __iomem *base,
++ const u16 *rst_map, int nr_resets);
++
+ static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
+ {
+ if (!desc->base_bits)
+@@ -552,7 +603,8 @@ static int en7523_clk_hw_init(struct platform_device *pdev,
+
+ en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
+
+- return 0;
++ return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map,
++ ARRAY_SIZE(en7523_rst_map));
+ }
+
+ static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
+@@ -652,7 +704,8 @@ static const struct reset_control_ops en7581_reset_ops = {
+ .status = en7523_reset_status,
+ };
+
+-static int en7581_reset_register(struct device *dev, void __iomem *base)
++static int en7581_reset_register(struct device *dev, void __iomem *base,
++ const u16 *rst_map, int nr_resets)
+ {
+ struct en_rst_data *rst_data;
+
+@@ -661,10 +714,10 @@ static int en7581_reset_register(struct device *dev, void __iomem *base)
+ return -ENOMEM;
+
+ rst_data->bank_ofs = en7581_rst_ofs;
+- rst_data->idx_map = en7581_rst_map;
++ rst_data->idx_map = rst_map;
+ rst_data->base = base;
+
+- rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
++ rst_data->rcdev.nr_resets = nr_resets;
+ rst_data->rcdev.of_xlate = en7523_reset_xlate;
+ rst_data->rcdev.ops = &en7581_reset_ops;
+ rst_data->rcdev.of_node = dev->of_node;
+@@ -698,7 +751,8 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
+ val = readl(base + REG_NP_SCU_PCIC);
+ writel(val | 3, base + REG_NP_SCU_PCIC);
+
+- return en7581_reset_register(&pdev->dev, base);
++ return en7581_reset_register(&pdev->dev, base, en7581_rst_map,
++ ARRAY_SIZE(en7581_rst_map));
+ }
+
+ static int en7523_clk_probe(struct platform_device *pdev)
+--
+2.39.5
+
--- /dev/null
+From 947643509279a605a09959a06d332bf027e8be57 Mon Sep 17 00:00:00 2001
+From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
+Date: Mon, 10 Nov 2025 06:56:43 +0300
+Subject: [PATCH] dt-bindings: clock: airoha: Add reset support to EN7523 clock
+ binding
+
+Introduce reset capability to EN7523 device-tree clock binding
+documentation.
+
+Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
+Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+index fe2c5c1baf43..a8471367175b 100644
+--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
++++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+@@ -64,8 +64,6 @@ allOf:
+ reg:
+ minItems: 2
+
+- '#reset-cells': false
+-
+ - if:
+ properties:
+ compatible:
+@@ -85,6 +83,7 @@ examples:
+ reg = <0x1fa20000 0x400>,
+ <0x1fb00000 0x1000>;
+ #clock-cells = <1>;
++ #reset-cells = <1>;
+ };
+
+ - |
+--
+2.39.5
+
--- /dev/null
+From 0f7c637d1103d79829dec198e5f1b678c1feb5f2 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Tue, 12 Nov 2024 01:08:48 +0100
+Subject: [PATCH] dt-bindings: clock: airoha: Update reg mapping for EN7581
+ SoC.
+
+clk-en7523 driver for EN7581 SoC is mapping all the scu memory region
+while it is configuring the chip-scu one via a syscon. Update the reg
+mapping definition for this device. This patch does not introduce any
+backward incompatibility since the dts for EN7581 SoC is not upstream
+yet.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-1-8ada5e394ae4@kernel.org
+Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ .../bindings/clock/airoha,en7523-scu.yaml | 23 +++++++------------
+ 1 file changed, 8 insertions(+), 15 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+index 84353fd09428..fe2c5c1baf43 100644
+--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
++++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+@@ -34,8 +34,10 @@ properties:
+ - airoha,en7581-scu
+
+ reg:
+- minItems: 2
+- maxItems: 4
++ items:
++ - description: scu base address
++ - description: misc scu base address
++ minItems: 1
+
+ "#clock-cells":
+ description:
+@@ -60,9 +62,7 @@ allOf:
+ then:
+ properties:
+ reg:
+- items:
+- - description: scu base address
+- - description: misc scu base address
++ minItems: 2
+
+ '#reset-cells': false
+
+@@ -73,11 +73,7 @@ allOf:
+ then:
+ properties:
+ reg:
+- items:
+- - description: scu base address
+- - description: misc scu base address
+- - description: reset base address
+- - description: pb scu base address
++ maxItems: 1
+
+ additionalProperties: false
+
+@@ -96,12 +92,9 @@ examples:
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+- scuclk: clock-controller@1fa20000 {
++ scuclk: clock-controller@1fb00000 {
+ compatible = "airoha,en7581-scu";
+- reg = <0x0 0x1fa20000 0x0 0x400>,
+- <0x0 0x1fb00000 0x0 0x90>,
+- <0x0 0x1fb00830 0x0 0x8>,
+- <0x0 0x1fbe3400 0x0 0xfc>;
++ reg = <0x0 0x1fb00000 0x0 0x970>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+--
+2.39.5
+
--- /dev/null
+From 947643509279a605a09959a06d332bf027e8be57 Mon Sep 17 00:00:00 2001
+From: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
+Date: Mon, 10 Nov 2025 06:56:43 +0300
+Subject: [PATCH] dt-bindings: clock: airoha: Add reset support to EN7523 clock
+ binding
+
+Introduce reset capability to EN7523 device-tree clock binding
+documentation.
+
+Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
+Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ .../dt-bindings/reset/airoha,en7523-reset.h | 61 +++++++++++++++++++
+ 1 file changed, 61 insertions(+)
+ create mode 100644 include/dt-bindings/reset/airoha,en7523-reset.h
+
+diff --git a/include/dt-bindings/reset/airoha,en7523-reset.h b/include/dt-bindings/reset/airoha,en7523-reset.h
+new file mode 100644
+index 000000000000..211e8a23a21c
+--- /dev/null
++++ b/include/dt-bindings/reset/airoha,en7523-reset.h
+@@ -0,0 +1,61 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2024 iopsys Software Solutions AB.
++ * Copyright (C) 2025 Genexis AB.
++ *
++ * Author: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
++ *
++ * based on
++ * include/dt-bindings/reset/airoha,en7581-reset.h
++ * by Lorenzo Bianconi <lorenzo@kernel.org>
++ */
++
++#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_
++#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_
++
++/* RST_CTRL2 */
++#define EN7523_XPON_PHY_RST 0
++#define EN7523_XSI_MAC_RST 1
++#define EN7523_XSI_PHY_RST 2
++#define EN7523_NPU_RST 3
++#define EN7523_I2S_RST 4
++#define EN7523_TRNG_RST 5
++#define EN7523_TRNG_MSTART_RST 6
++#define EN7523_DUAL_HSI0_RST 7
++#define EN7523_DUAL_HSI1_RST 8
++#define EN7523_HSI_RST 9
++#define EN7523_DUAL_HSI0_MAC_RST 10
++#define EN7523_DUAL_HSI1_MAC_RST 11
++#define EN7523_HSI_MAC_RST 12
++#define EN7523_WDMA_RST 13
++#define EN7523_WOE0_RST 14
++#define EN7523_WOE1_RST 15
++#define EN7523_HSDMA_RST 16
++#define EN7523_I2C2RBUS_RST 17
++#define EN7523_TDMA_RST 18
++/* RST_CTRL1 */
++#define EN7523_PCM1_ZSI_ISI_RST 19
++#define EN7523_FE_PDMA_RST 20
++#define EN7523_FE_QDMA_RST 21
++#define EN7523_PCM_SPIWP_RST 22
++#define EN7523_CRYPTO_RST 23
++#define EN7523_TIMER_RST 24
++#define EN7523_PCM1_RST 25
++#define EN7523_UART_RST 26
++#define EN7523_GPIO_RST 27
++#define EN7523_GDMA_RST 28
++#define EN7523_I2C_MASTER_RST 29
++#define EN7523_PCM2_ZSI_ISI_RST 30
++#define EN7523_SFC_RST 31
++#define EN7523_UART2_RST 32
++#define EN7523_GDMP_RST 33
++#define EN7523_FE_RST 34
++#define EN7523_USB_HOST_P0_RST 35
++#define EN7523_GSW_RST 36
++#define EN7523_SFC2_PCM_RST 37
++#define EN7523_PCIE0_RST 38
++#define EN7523_PCIE1_RST 39
++#define EN7523_PCIE_HB_RST 40
++#define EN7523_XPON_MAC_RST 41
++
++#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ */
+--
+2.39.5
+
--- /dev/null
+From 02d3b7557ce28c373ea1e925ae16ab5988284313 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 14 Jan 2025 00:10:03 +0100
+Subject: [PATCH 1/2] dt-bindings: clock: drop NUM_CLOCKS define for EN7581
+
+Drop NUM_CLOCKS define for EN7581 include. This is not a binding and
+should not be placed here. Value is derived internally in the user
+driver.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20250113231030.6735-3-ansuelsmth@gmail.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ include/dt-bindings/clock/en7523-clk.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/include/dt-bindings/clock/en7523-clk.h b/include/dt-bindings/clock/en7523-clk.h
+index 717d23a5e5ae..28e56745ccff 100644
+--- a/include/dt-bindings/clock/en7523-clk.h
++++ b/include/dt-bindings/clock/en7523-clk.h
+@@ -12,6 +12,4 @@
+ #define EN7523_CLK_CRYPTO 6
+ #define EN7523_CLK_PCIE 7
+
+-#define EN7523_NUM_CLOCKS 8
+-
+ #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */
+--
+2.39.5
+
--- /dev/null
+From 82108ad3285f58f314ad41398f44017c7dbe44de Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 14 Jan 2025 00:10:04 +0100
+Subject: [PATCH 2/2] dt-bindings: clock: add ID for eMMC for EN7581
+
+Add ID for eMMC for EN7581. This is to control clock selection of eMMC
+between 200MHz and 150MHz.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Acked-by: Conor Dooley <conor.dooley@microchip.com>
+Link: https://lore.kernel.org/r/20250113231030.6735-4-ansuelsmth@gmail.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ include/dt-bindings/clock/en7523-clk.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/dt-bindings/clock/en7523-clk.h b/include/dt-bindings/clock/en7523-clk.h
+index 28e56745ccff..edfa64045f52 100644
+--- a/include/dt-bindings/clock/en7523-clk.h
++++ b/include/dt-bindings/clock/en7523-clk.h
+@@ -12,4 +12,6 @@
+ #define EN7523_CLK_CRYPTO 6
+ #define EN7523_CLK_PCIE 7
+
++#define EN7581_CLK_EMMC 8
++
+ #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */
+--
+2.39.5
+
--- /dev/null
+From f3fa5911b1f094e164c497f7b10d94d92852e285 Mon Sep 17 00:00:00 2001
+From: Caleb James DeLisle <cjd@cjdns.fr>
+Date: Wed, 14 Jan 2026 17:54:05 +0000
+Subject: [PATCH] dt-bindings: clock, reset: Add econet EN751221 bindings
+
+Add clock and reset bindings for EN751221 based on the Airoha EN7523 SCU
+driver.
+
+Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
+---
+The EN751221 has the same bifurcation of SCU as EN7581 so we use
+the same chip-scu as airoha,en7581-chip-scu.
+---
+ .../bindings/clock/airoha,en7523-scu.yaml | 17 +++++++-
+ .../mips/econet,en751221-chip-scu.yaml | 42 +++++++++++++++++++
+ .../dt-bindings/clock/econet,en751221-scu.h | 14 +++++++
+ .../dt-bindings/reset/econet,en751221-scu.h | 41 ++++++++++++++++++
+ 4 files changed, 113 insertions(+), 1 deletion(-)
+ create mode 100644 Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml
+ create mode 100644 include/dt-bindings/clock/econet,en751221-scu.h
+ create mode 100644 include/dt-bindings/reset/econet,en751221-scu.h
+
+--- 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,14 @@ examples:
+ #reset-cells = <1>;
+ };
+ };
++
++ - |
++ soc {
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ scuclk: clock-controller@1fb00000 {
++ compatible = "econet,en751221-scu";
++ reg = <0x1fb00000 0x970>;
++ };
++ };
+\ No newline at end of file
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml
+@@ -0,0 +1,42 @@
++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/arm/airoha,en7581-chip-scu.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: EcoNet Chip SCU Controller for EN751221 SoC
++
++maintainers:
++ - Caleb James DeLisle <cjd@cjdns.fr>
++
++description:
++ The EcoNet chip-scu block provides a configuration interface for clock,
++ io-muxing and other functionalities used by multiple controllers (e.g. clock,
++ pinctrl, ecc) on EN751221 SoC.
++
++properties:
++ compatible:
++ items:
++ - enum:
++ - econet,en751221-chip-scu
++ - const: syscon
++
++ reg:
++ maxItems: 1
++
++required:
++ - compatible
++ - reg
++
++additionalProperties: false
++
++examples:
++ - |
++ soc {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ syscon@1fa20000 {
++ compatible = "econet,en751221-chip-scu", "syscon";
++ reg = <0x1fa20000 0x388>;
++ };
++ };
+--- /dev/null
++++ b/include/dt-bindings/clock/econet,en751221-scu.h
+@@ -0,0 +1,15 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
++
++#ifndef _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_
++#define _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_
++
++#define EN751221_CLK_PCIE 0
++#define EN751221_CLK_SPI 1
++#define EN751221_CLK_BUS 2
++#define EN751221_CLK_CPU 3
++#define EN751221_CLK_HPT 4
++#define EN751221_CLK_GSW 5
++
++#define EN751221_MAX_CLKS 6
++
++#endif /* _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ */
+\ No newline at end of file
+--- /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_ */
--- /dev/null
+From 1dfb29374a040ba80d378b3465f4e0bcb67f4ba3 Mon Sep 17 00:00:00 2001
+From: Caleb James DeLisle <cjd@cjdns.fr>
+Date: Wed, 14 Jan 2026 18:06:13 +0000
+Subject: [PATCH] clk: airoha: Add econet EN751221 clock/reset support to
+ en7523-scu
+
+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 | 182 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 185 insertions(+), 3 deletions(-)
+
+--- a/drivers/clk/Kconfig
++++ b/drivers/clk/Kconfig
+@@ -210,13 +210,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"
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+
++#include <linux/bitfield.h>
+ #include <linux/delay.h>
+ #include <linux/clk-provider.h>
+ #include <linux/io.h>
+@@ -11,6 +12,8 @@
+ #include <dt-bindings/clock/en7523-clk.h>
+ #include <dt-bindings/reset/airoha,en7523-reset.h>
+ #include <dt-bindings/reset/airoha,en7581-reset.h>
++#include <dt-bindings/clock/econet,en751221-scu.h>
++#include <dt-bindings/reset/econet,en751221-scu.h>
+
+ #define RST_NR_PER_BANK 32
+
+@@ -33,15 +36,47 @@
+ #define REG_RESET_CONTROL_PCIEHB BIT(29)
+ #define REG_RESET_CONTROL_PCIE1 BIT(27)
+ #define REG_RESET_CONTROL_PCIE2 BIT(26)
++#define REG_HIR 0x064
++#define REG_HIR_MASK GENMASK(31, 16)
+ /* EN7581 */
+ #define REG_NP_SCU_PCIC 0x88
+ #define REG_NP_SCU_SSTR 0x9c
+ #define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
+ #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
+ #define REG_CRYPTO_CLKSRC2 0x20c
++/* EN751221 */
++#define EN751221_REG_SPI_DIV 0x0cc
++#define EN751221_REG_SPI_DIV_MASK GENMASK(31,8)
++#define EN751221_SPI_BASE 500000000
++#define EN751221_SPI_BASE_EN7526C 400000000
++#define EN751221_REG_BUS 0x284
++#define EN751221_REG_BUS_MASK GENMASK(21,12)
++#define EN751221_REG_SSR3 0x094
++#define EN751221_REG_SSR3_GSW_MASK GENMASK(9,8)
+
+ #define REG_RST_CTRL2 0x830
+ #define REG_RST_CTRL1 0x834
++#define EN751221_REG_RST_DMT 0x84
++#define EN751221_REG_RST_USB 0xec
++
++enum en_hir {
++ HIR_UNKNOWN = -1,
++ HIR_TC3169 = 0,
++ HIR_TC3182 = 1,
++ HIR_RT65168 = 2,
++ HIR_RT63165 = 3,
++ HIR_RT63365 = 4,
++ HIR_MT751020 = 5,
++ HIR_MT7505 = 6,
++ HIR_EN751221 = 7,
++ HIR_EN7526C = 8,
++ HIR_EN751627 = 9,
++ HIR_EN7580 = 10,
++ HIR_EN7528 = 11,
++ HIR_EN7523 = 12,
++ HIR_EN7581 = 13,
++ HIR_MAX = 14,
++};
+
+ struct en_clk_desc {
+ int id;
+@@ -93,6 +128,8 @@ static const u32 bus7581_base[] = { 6000
+ static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
+ static const u32 crypto_base[] = { 540000000, 480000000 };
+ static const u32 emmc7581_base[] = { 200000000, 150000000 };
++/* EN751221 */
++static const u32 gsw751221_base[] = { 500000000, 250000000, 400000000, 200000000 };
+
+ static const struct en_clk_desc en7523_base_clks[] = {
+ {
+@@ -300,6 +337,13 @@ static const u16 en7581_rst_ofs[] = {
+ REG_RST_CTRL1,
+ };
+
++static const u16 en751221_rst_ofs[] = {
++ REG_RST_CTRL2,
++ REG_RST_CTRL1,
++ EN751221_REG_RST_DMT,
++ EN751221_REG_RST_USB,
++};
++
+ static const u16 en7523_rst_map[] = {
+ /* RST_CTRL2 */
+ [EN7523_XPON_PHY_RST] = 0,
+@@ -405,8 +449,61 @@ static const u16 en7581_rst_map[] = {
+ [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
+ };
+
++static const u16 en751221_rst_map[] = {
++ /* RST_CTRL2 */
++ [EN751221_XPON_PHY_RST] = 0,
++ [EN751221_GFAST_RST] = 1,
++ [EN751221_CPU_TIMER2_RST] = 2,
++ [EN751221_UART3_RST] = 3,
++ [EN751221_UART4_RST] = 4,
++ [EN751221_UART5_RST] = 5,
++ [EN751221_I2C2_RST] = 6,
++ [EN751221_XSI_MAC_RST] = 7,
++ [EN751221_XSI_PHY_RST] = 8,
++
++ /* RST_CTRL1 */
++ [EN751221_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0,
++ [EN751221_FE_QDMA1_RST] = RST_NR_PER_BANK + 1,
++ [EN751221_FE_QDMA2_RST] = RST_NR_PER_BANK + 2,
++ [EN751221_FE_UNZIP_RST] = RST_NR_PER_BANK + 3,
++ [EN751221_PCM2_RST] = RST_NR_PER_BANK + 4,
++ [EN751221_PTM_MAC_RST] = RST_NR_PER_BANK + 5,
++ [EN751221_CRYPTO_RST] = RST_NR_PER_BANK + 6,
++ [EN751221_SAR_RST] = RST_NR_PER_BANK + 7,
++ [EN751221_TIMER_RST] = RST_NR_PER_BANK + 8,
++ [EN751221_INTC_RST] = RST_NR_PER_BANK + 9,
++ [EN751221_BONDING_RST] = RST_NR_PER_BANK + 10,
++ [EN751221_PCM1_RST] = RST_NR_PER_BANK + 11,
++ [EN751221_UART_RST] = RST_NR_PER_BANK + 12,
++ [EN751221_GPIO_RST] = RST_NR_PER_BANK + 13,
++ [EN751221_GDMA_RST] = RST_NR_PER_BANK + 14,
++ [EN751221_I2C_MASTER_RST] = RST_NR_PER_BANK + 16,
++ [EN751221_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17,
++ [EN751221_SFC_RST] = RST_NR_PER_BANK + 18,
++ [EN751221_UART2_RST] = RST_NR_PER_BANK + 19,
++ [EN751221_GDMP_RST] = RST_NR_PER_BANK + 20,
++ [EN751221_FE_RST] = RST_NR_PER_BANK + 21,
++ [EN751221_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22,
++ [EN751221_GSW_RST] = RST_NR_PER_BANK + 23,
++ [EN751221_SFC2_PCM_RST] = RST_NR_PER_BANK + 25,
++ [EN751221_PCIE0_RST] = RST_NR_PER_BANK + 26,
++ [EN751221_PCIE1_RST] = RST_NR_PER_BANK + 27,
++ [EN751221_CPU_TIMER_RST] = RST_NR_PER_BANK + 28,
++ [EN751221_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
++ [EN751221_SIMIF_RST] = RST_NR_PER_BANK + 30,
++ [EN751221_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
++
++ /* RST_DMT */
++ [EN751221_DMT_RST] = 2 * RST_NR_PER_BANK + 0,
++
++ /* RST_USB */
++ [EN751221_USB_PHY_P0_RST] = 3 * RST_NR_PER_BANK + 6,
++ [EN751221_USB_PHY_P1_RST] = 3 * RST_NR_PER_BANK + 7,
++};
++
+ static int en7581_reset_register(struct device *dev, void __iomem *base,
+- const u16 *rst_map, int nr_resets);
++ const u16 *rst_map, int nr_resets,
++ const u16 *rst_reg_ofs);
+
+ static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
+ {
+@@ -604,7 +701,8 @@ static int en7523_clk_hw_init(struct pla
+ en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
+
+ return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map,
+- ARRAY_SIZE(en7523_rst_map));
++ ARRAY_SIZE(en7523_rst_map),
++ en7581_rst_ofs);
+ }
+
+ static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
+@@ -705,7 +803,8 @@ static const struct reset_control_ops en
+ };
+
+ static int en7581_reset_register(struct device *dev, void __iomem *base,
+- const u16 *rst_map, int nr_resets)
++ const u16 *rst_map, int nr_resets,
++ const u16 *rst_reg_ofs)
+ {
+ struct en_rst_data *rst_data;
+
+@@ -713,7 +812,7 @@ static int en7581_reset_register(struct
+ if (!rst_data)
+ return -ENOMEM;
+
+- rst_data->bank_ofs = en7581_rst_ofs;
++ rst_data->bank_ofs = rst_reg_ofs;
+ rst_data->idx_map = rst_map;
+ rst_data->base = base;
+
+@@ -752,7 +851,123 @@ static int en7581_clk_hw_init(struct pla
+ writel(val | 3, base + REG_NP_SCU_PCIC);
+
+ return en7581_reset_register(&pdev->dev, base, en7581_rst_map,
+- ARRAY_SIZE(en7581_rst_map));
++ ARRAY_SIZE(en7581_rst_map),
++ en7581_rst_ofs);
++}
++
++static enum en_hir get_hw_id(void __iomem *np_base)
++{
++ u32 val = FIELD_GET(REG_HIR_MASK, readl(np_base + REG_HIR));
++
++ if (val < HIR_MAX)
++ return (enum en_hir) val;
++
++ return HIR_UNKNOWN;
++}
++
++static void en751221_try_register_clk(struct device *dev, int key,
++ struct clk_hw_onecell_data *clk_data,
++ const char *name, u32 rate)
++{
++ struct clk_hw *hw;
++
++ hw = clk_hw_register_fixed_rate(dev, name, NULL, 0, rate);
++ if (IS_ERR(hw))
++ pr_err("Failed to register clk %s: %pe\n", name, hw);
++ else
++ clk_data->hws[key] = hw;
++}
++
++static void en751221_register_clocks(struct device *dev,
++ struct clk_hw_onecell_data *clk_data,
++ struct regmap *map, void __iomem *np_base)
++{
++ enum en_hir hid = get_hw_id(np_base);
++ struct clk_hw *hw;
++ u32 rate;
++ u32 div;
++ int err;
++
++ /* PCI */
++ hw = en7523_register_pcie_clk(dev, np_base);
++ clk_data->hws[EN751221_CLK_PCIE] = hw;
++
++ /* SPI */
++ rate = EN751221_SPI_BASE;
++ if (hid == HIR_EN7526C)
++ rate = EN751221_SPI_BASE_EN7526C;
++
++ err = regmap_read(map, EN751221_REG_SPI_DIV, &div);
++ if (err) {
++ pr_err("Failed reading fixed clk div %s: %d\n",
++ "spi", err);
++ } else {
++ div = FIELD_GET(EN751221_REG_SPI_DIV_MASK, div) * 2;
++ if (!div)
++ div = 40;
++
++ en751221_try_register_clk(dev, EN751221_CLK_SPI, clk_data,
++ "spi", rate / div);
++ }
++
++ /* BUS */
++ rate = FIELD_GET(EN751221_REG_BUS_MASK,
++ readl(np_base + EN751221_REG_BUS));
++ rate *= 1000000;
++ en751221_try_register_clk(dev, EN751221_CLK_BUS, clk_data, "bus",
++ rate);
++
++ /* CPU */
++ en751221_try_register_clk(dev, EN751221_CLK_CPU, clk_data, "cpu",
++ rate * 4);
++
++ /* HPT */
++ switch (hid) {
++ case HIR_EN751221:
++ case HIR_EN751627:
++ case HIR_EN7526C:
++ case HIR_EN7580:
++ case HIR_EN7528:
++ rate = 200000000;
++ break;
++ case HIR_MT7505:
++ rate = 100000000;
++ break;
++ case HIR_MT751020:
++ rate = 800000000 / 3;
++ break;
++ default:
++ rate = 250000000;
++ }
++ en751221_try_register_clk(dev, EN751221_CLK_HPT, clk_data, "hpt",
++ rate);
++
++ /* GSW */
++ rate = FIELD_GET(EN751221_REG_SSR3_GSW_MASK,
++ readl(np_base + EN751221_REG_SSR3));
++ en751221_try_register_clk(dev, EN751221_CLK_GSW, clk_data, "gsw",
++ gsw751221_base[rate]);
++}
++
++static int en751221_clk_hw_init(struct platform_device *pdev,
++ struct clk_hw_onecell_data *clk_data)
++{
++ struct regmap *map;
++ void __iomem *base;
++
++ map = syscon_regmap_lookup_by_compatible("econet,en751221-chip-scu");
++ if (IS_ERR(map))
++ return PTR_ERR(map);
++
++ base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
++
++ en751221_register_clocks(&pdev->dev, clk_data, map, base);
++
++ return en7581_reset_register(&pdev->dev, base, en751221_rst_map,
++ ARRAY_SIZE(en751221_rst_map),
++ en751221_rst_ofs);
+ }
+
+ static int en7523_clk_probe(struct platform_device *pdev)
+@@ -799,9 +1014,20 @@ static const struct en_clk_soc_data en75
+ .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 */ }
+ };
+