Based on upstream Linux:
  aba86f7bff0b ("reset: spacemit: Extract common K1 reset code")

Extract the common reset controller code from the K1 driver into
separate reset-spacemit-common.{c,h} files to prepare for additional
SpacemiT SoCs that share the same reset controller architecture.

Signed-off-by: Yixun Lan <[email protected]>
---
 drivers/clk/spacemit/Kconfig                   |   1 +
 drivers/reset/Kconfig                          |   1 +
 drivers/reset/Makefile                         |   2 +-
 drivers/reset/spacemit/Kconfig                 |  15 +++
 drivers/reset/spacemit/Makefile                |   3 +-
 drivers/reset/spacemit/reset-spacemit-common.c |  93 ++++++++++++++++++
 drivers/reset/spacemit/reset-spacemit-common.h |  40 ++++++++
 drivers/reset/spacemit/reset-spacemit-k1.c     | 128 ++-----------------------
 8 files changed, 163 insertions(+), 120 deletions(-)

diff --git a/drivers/clk/spacemit/Kconfig b/drivers/clk/spacemit/Kconfig
index b22f65f2547..c305f433871 100644
--- a/drivers/clk/spacemit/Kconfig
+++ b/drivers/clk/spacemit/Kconfig
@@ -16,6 +16,7 @@ if CLK_SPACEMIT
 config CLK_SPACEMIT_K1
        bool "SpacemiT K1 clock support"
        select CLK_CCF
+       select RESET_SPACEMIT_K1
        help
          This enables support clock driver for Spacemit K1 SoC.
          It's based on Common Clock Framework.
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index db764ed5ace..ad61ebf344a 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -280,4 +280,5 @@ config RESET_RZG2L_USBPHY_CTRL
          SoC.
 
 source "drivers/reset/stm32/Kconfig"
+source "drivers/reset/spacemit/Kconfig"
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 384f4336331..959aafe4d70 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_RESET_DRA7) += reset-dra7.o
 obj-$(CONFIG_RESET_AT91) += reset-at91.o
 obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o
 obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
-obj-$(CONFIG_CLK_SPACEMIT_K1) += spacemit/
+obj-$(CONFIG_RESET_SPACEMIT_COMMON) += spacemit/
 
 obj-$(CONFIG_ARCH_STM32) += stm32/
 obj-$(CONFIG_ARCH_STM32MP) += stm32/
diff --git a/drivers/reset/spacemit/Kconfig b/drivers/reset/spacemit/Kconfig
new file mode 100644
index 00000000000..20e4cc6e4d8
--- /dev/null
+++ b/drivers/reset/spacemit/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config RESET_SPACEMIT_COMMON
+       bool
+       select DM_RESET
+       help
+         Common reset controller infrastructure for SpacemiT SoCs.
+         Shared by the K1 and K3 reset drivers.
+
+config RESET_SPACEMIT_K1
+       bool "SpacemiT K1 reset support"
+       select RESET_SPACEMIT_COMMON
+       help
+         Reset controller for SpacemiT K1 (MPMU/APBC/APMU/APBC2).
+         Bound from the K1 CCU/syscon devices.
diff --git a/drivers/reset/spacemit/Makefile b/drivers/reset/spacemit/Makefile
index 16722c68954..56f9fd1ab20 100644
--- a/drivers/reset/spacemit/Makefile
+++ b/drivers/reset/spacemit/Makefile
@@ -2,4 +2,5 @@
 #
 # SpacemiT reset drivers
 
-obj-y += reset-spacemit-k1.o
+obj-$(CONFIG_RESET_SPACEMIT_COMMON)    += reset-spacemit-common.o
+obj-$(CONFIG_RESET_SPACEMIT_K1)                += reset-spacemit-k1.o
diff --git a/drivers/reset/spacemit/reset-spacemit-common.c 
b/drivers/reset/spacemit/reset-spacemit-common.c
new file mode 100644
index 00000000000..34ed0862b9c
--- /dev/null
+++ b/drivers/reset/spacemit/reset-spacemit-common.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SpacemiT reset controller — common implementation (U-Boot)
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <malloc.h>
+#include <reset-uclass.h>
+
+#include "reset-spacemit-common.h"
+
+static int spacemit_reset_xfer(struct reset_ctl *rst, bool assert)
+{
+       struct spacemit_reset_priv *priv = dev_get_priv(rst->dev);
+       const struct spacemit_reset_data *e;
+       u32 v;
+
+       if (rst->id >= priv->table_size)
+               return -EINVAL;
+
+       e = &priv->table[rst->id];
+       if (e->assert_mask == 0 && e->deassert_mask == 0)
+               return -EINVAL;
+
+       v = readl(priv->base + e->offset);
+       v &= ~(e->assert_mask | e->deassert_mask);
+       v |= assert ? e->assert_mask : e->deassert_mask;
+       writel(v, priv->base + e->offset);
+
+       return 0;
+}
+
+static int spacemit_reset_assert(struct reset_ctl *rst)
+{
+       return spacemit_reset_xfer(rst, true);
+}
+
+static int spacemit_reset_deassert(struct reset_ctl *rst)
+{
+       return spacemit_reset_xfer(rst, false);
+}
+
+static int spacemit_reset_request(struct reset_ctl *rst)
+{
+       struct spacemit_reset_priv *priv = dev_get_priv(rst->dev);
+
+       return rst->id < priv->table_size ? 0 : -EINVAL;
+}
+
+const struct reset_ops spacemit_reset_ops = {
+       .request        = spacemit_reset_request,
+       .rst_assert     = spacemit_reset_assert,
+       .rst_deassert   = spacemit_reset_deassert,
+};
+
+int spacemit_reset_probe(struct udevice *dev)
+{
+       struct spacemit_reset_priv *priv = dev_get_priv(dev);
+
+       priv->base = (void __iomem *)dev_remap_addr(dev);
+       if (!priv->base)
+               return -ENODEV;
+
+       return 0;
+}
+
+int spacemit_reset_bind(struct udevice *parent, const char *drv_name,
+                       const struct spacemit_reset_data *table,
+                       size_t table_size)
+{
+       struct spacemit_reset_priv *priv;
+       struct udevice *rst_dev;
+       int ret;
+
+       ret = device_bind_driver_to_node(parent, drv_name, "reset",
+                                        dev_ofnode(parent), &rst_dev);
+       if (ret)
+               return ret;
+
+       priv = malloc(sizeof(*priv));
+       if (!priv) {
+               device_unbind(rst_dev);
+               return -ENOMEM;
+       }
+       priv->table = table;
+       priv->table_size = table_size;
+       dev_set_priv(rst_dev, priv);
+
+       return 0;
+}
diff --git a/drivers/reset/spacemit/reset-spacemit-common.h 
b/drivers/reset/spacemit/reset-spacemit-common.h
new file mode 100644
index 00000000000..cde52b3fc1d
--- /dev/null
+++ b/drivers/reset/spacemit/reset-spacemit-common.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * SpacemiT reset controller — common definitions (U-Boot)
+ */
+
+#ifndef _RESET_SPACEMIT_COMMON_H_
+#define _RESET_SPACEMIT_COMMON_H_
+
+#include <linux/types.h>
+
+struct udevice;
+struct reset_ops;
+
+struct spacemit_reset_data {
+       u32 offset;
+       u32 assert_mask;
+       u32 deassert_mask;
+};
+
+struct spacemit_reset_priv {
+       void *base;
+       const struct spacemit_reset_data *table;
+       size_t table_size;
+};
+
+#define RESET_DATA(_offset, _assert_mask, _deassert_mask)      \
+       {                                                       \
+               .offset         = (_offset),                    \
+               .assert_mask    = (_assert_mask),               \
+               .deassert_mask  = (_deassert_mask),             \
+       }
+
+extern const struct reset_ops spacemit_reset_ops;
+
+int spacemit_reset_probe(struct udevice *dev);
+int spacemit_reset_bind(struct udevice *parent, const char *drv_name,
+                       const struct spacemit_reset_data *table,
+                       size_t table_size);
+
+#endif /* _RESET_SPACEMIT_COMMON_H_ */
diff --git a/drivers/reset/spacemit/reset-spacemit-k1.c 
b/drivers/reset/spacemit/reset-spacemit-k1.c
index 129e1cc96f1..75000ff64e0 100644
--- a/drivers/reset/spacemit/reset-spacemit-k1.c
+++ b/drivers/reset/spacemit/reset-spacemit-k1.c
@@ -7,46 +7,19 @@
  * Copyright (C) 2026 RISCstar Ltd.
  */
 
-#include <asm/io.h>
 #include <dm.h>
-#include <dm/device-internal.h>
-#include <dm/lists.h>
 #include <dt-bindings/clock/spacemit,k1-syscon.h>
 #include <linux/bitops.h>
-#include <malloc.h>
-#include <reset-uclass.h>
 #include <soc/spacemit/k1-reset.h>
 #include <soc/spacemit/k1-syscon.h>
 
-/* ===================================================================
- * Per-syscon reset signal tables.
- *
- * Indexed by the kernel-side per-syscon-local IDs from
- * <dt-bindings/clock/spacemit,k1-syscon.h>. Each entry is
- * (offset, assert_mask, deassert_mask): bits in assert_mask are set
- * when the reset line is asserted; bits in deassert_mask are set when
- * deasserted; the union (assert_mask | deassert_mask) is the set of
- * bits the controller will overwrite on each transition.
- *
- * Layout mirrors the kernel-side K1 reset driver.
- * ===================================================================
- */
-
-struct spacemit_k1_reset_data {
-       u32 offset;
-       u32 assert_mask;
-       u32 deassert_mask;
-};
+#include "reset-spacemit-common.h"
 
-#define RESET_DATA(o, a, d) {                                  \
-       .offset = (o), .assert_mask = (a), .deassert_mask = (d) \
-}
-
-static const struct spacemit_k1_reset_data k1_mpmu_resets[] = {
+static const struct spacemit_reset_data k1_mpmu_resets[] = {
        [RESET_WDT]     = RESET_DATA(MPMU_WDTPCR,               BIT(2), 0),
 };
 
-static const struct spacemit_k1_reset_data k1_apbc_resets[] = {
+static const struct spacemit_reset_data k1_apbc_resets[] = {
        [RESET_UART0]   = RESET_DATA(APBC_UART1_CLK_RST,        BIT(2), 0),
        [RESET_UART2]   = RESET_DATA(APBC_UART2_CLK_RST,        BIT(2), 0),
        [RESET_UART3]   = RESET_DATA(APBC_UART3_CLK_RST,        BIT(2), 0),
@@ -100,7 +73,7 @@ static const struct spacemit_k1_reset_data k1_apbc_resets[] 
= {
        [RESET_CAN0]    = RESET_DATA(APBC_CAN0_CLK_RST,         BIT(2), 0),
 };
 
-static const struct spacemit_k1_reset_data k1_apmu_resets[] = {
+static const struct spacemit_reset_data k1_apmu_resets[] = {
        [RESET_CCIC_4X]         = RESET_DATA(APMU_CCIC_CLK_RES_CTRL,    0, 
BIT(1)),
        [RESET_CCIC1_PHY]       = RESET_DATA(APMU_CCIC_CLK_RES_CTRL,    0, 
BIT(2)),
        [RESET_SDH_AXI]         = RESET_DATA(APMU_SDH0_CLK_RES_CTRL,    0, 
BIT(0)),
@@ -156,7 +129,7 @@ static const struct spacemit_k1_reset_data k1_apmu_resets[] 
= {
        [RESET_MC]              = RESET_DATA(APMU_PMUA_MC_CTRL,         0, 
BIT(0)),
 };
 
-static const struct spacemit_k1_reset_data k1_apbc2_resets[] = {
+static const struct spacemit_reset_data k1_apbc2_resets[] = {
        [RESET_APBC2_UART1]     = RESET_DATA(APBC2_UART1_CLK_RST,       BIT(2), 
0),
        [RESET_APBC2_SSP2]      = RESET_DATA(APBC2_SSP2_CLK_RST,        BIT(2), 
0),
        [RESET_APBC2_TWSI3]     = RESET_DATA(APBC2_TWSI3_CLK_RST,       BIT(2), 
0),
@@ -166,89 +139,22 @@ static const struct spacemit_k1_reset_data 
k1_apbc2_resets[] = {
        [RESET_APBC2_GPIO]      = RESET_DATA(APBC2_GPIO_CLK_RST,        BIT(2), 
0),
 };
 
-/* ===================================================================
- * Driver
- * ===================================================================
- */
-
-struct spacemit_k1_reset_priv {
-       void __iomem *base;
-       const struct spacemit_k1_reset_data *table;
-       size_t table_size;
-};
-
-static int spacemit_k1_reset_xfer(struct reset_ctl *rst, bool assert)
-{
-       struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev);
-       const struct spacemit_k1_reset_data *e;
-       u32 v;
-
-       if (rst->id >= priv->table_size)
-               return -EINVAL;
-
-       e = &priv->table[rst->id];
-       if (e->assert_mask == 0 && e->deassert_mask == 0)
-               return -EINVAL; /* not owned by this syscon */
-
-       v = readl(priv->base + e->offset);
-       v &= ~(e->assert_mask | e->deassert_mask);
-       v |= assert ? e->assert_mask : e->deassert_mask;
-       writel(v, priv->base + e->offset);
-
-       return 0;
-}
-
-static int spacemit_k1_reset_assert(struct reset_ctl *rst)
-{
-       return spacemit_k1_reset_xfer(rst, true);
-}
-
-static int spacemit_k1_reset_deassert(struct reset_ctl *rst)
-{
-       return spacemit_k1_reset_xfer(rst, false);
-}
-
-static int spacemit_k1_reset_request(struct reset_ctl *rst)
-{
-       struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev);
-
-       return rst->id < priv->table_size ? 0 : -EINVAL;
-}
-
-static const struct reset_ops spacemit_k1_reset_ops = {
-       .request        = spacemit_k1_reset_request,
-       .rst_assert     = spacemit_k1_reset_assert,
-       .rst_deassert   = spacemit_k1_reset_deassert,
-};
-
-static int spacemit_k1_reset_probe(struct udevice *dev)
-{
-       struct spacemit_k1_reset_priv *priv = dev_get_priv(dev);
 
-       priv->base = (void __iomem *)dev_remap_addr(dev);
-       if (!priv->base)
-               return -ENODEV;
-
-       return 0;
-}
 
 U_BOOT_DRIVER(spacemit_k1_reset) = {
        .name           = "spacemit_k1_reset",
        .id             = UCLASS_RESET,
-       .ops            = &spacemit_k1_reset_ops,
-       .probe          = spacemit_k1_reset_probe,
-       .priv_auto      = sizeof(struct spacemit_k1_reset_priv),
+       .ops            = &spacemit_reset_ops,
+       .probe          = spacemit_reset_probe,
+       .priv_auto      = sizeof(struct spacemit_reset_priv),
        .flags          = DM_FLAG_PRE_RELOC,
 };
 
 int spacemit_k1_reset_bind(struct udevice *parent,
                           enum spacemit_k1_reset_syscon syscon)
 {
-       struct spacemit_k1_reset_priv *priv;
-       struct udevice *rst_dev;
-       const struct spacemit_k1_reset_data *table;
+       const struct spacemit_reset_data *table;
        size_t table_size;
-       int ret;
 
        switch (syscon) {
        case SPACEMIT_K1_RESET_MPMU:
@@ -271,19 +177,5 @@ int spacemit_k1_reset_bind(struct udevice *parent,
                return -EINVAL;
        }
 
-       ret = device_bind_driver_to_node(parent, "spacemit_k1_reset", "reset",
-                                        dev_ofnode(parent), &rst_dev);
-       if (ret)
-               return ret;
-
-       priv = malloc(sizeof(*priv));
-       if (!priv) {
-               device_unbind(rst_dev);
-               return -ENOMEM;
-       }
-       priv->table = table;
-       priv->table_size = table_size;
-       dev_set_priv(rst_dev, priv);
-
-       return 0;
+       return spacemit_reset_bind(parent, "spacemit_k1_reset", table, 
table_size);
 }

-- 
2.55.0

Reply via email to