summaryrefslogtreecommitdiff
path: root/drivers/reset
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/reset')
-rw-r--r--drivers/reset/Kconfig44
-rw-r--r--drivers/reset/Makefile7
-rw-r--r--drivers/reset/reset-ast2500.c6
-rw-r--r--drivers/reset/reset-ast2600.c6
-rw-r--r--drivers/reset/reset-ast2700.c82
-rw-r--r--drivers/reset/reset-at91.c2
-rw-r--r--drivers/reset/reset-bcm6345.c2
-rw-r--r--drivers/reset/reset-brcmstb-rescal.c103
-rw-r--r--drivers/reset/reset-brcmstb.c97
-rw-r--r--drivers/reset/reset-dra7.c2
-rw-r--r--drivers/reset/reset-mediatek.c2
-rw-r--r--drivers/reset/reset-meson.c2
-rw-r--r--drivers/reset/reset-npcm.c2
-rw-r--r--drivers/reset/reset-raspberrypi.c2
-rw-r--r--drivers/reset/reset-spacemit-k1.c548
-rw-r--r--drivers/reset/reset-sunxi.c2
-rw-r--r--drivers/reset/reset-uclass.c34
-rw-r--r--drivers/reset/reset-zynqmp.c11
-rw-r--r--drivers/reset/sandbox-reset-test.c14
-rw-r--r--drivers/reset/sandbox-reset.c60
-rw-r--r--drivers/reset/spacemit/Makefile5
-rw-r--r--drivers/reset/spacemit/reset-spacemit-k1.c289
-rw-r--r--drivers/reset/sti-reset.c2
-rw-r--r--drivers/reset/stm32/stm32-reset-mp21.c2
-rw-r--r--drivers/reset/tegra-car-reset.c2
-rw-r--r--drivers/reset/tegra186-reset.c2
26 files changed, 752 insertions, 578 deletions
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 66911199c8b..db764ed5ace 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -64,6 +64,22 @@ config RESET_BCM6345
help
Support reset controller on BCM6345.
+config RESET_BRCMSTB
+ depends on ARCH_BCM283X
+ bool "Generic Reset controller driver for Broadcom"
+ help
+ This enables reset controller for Broadcom devices.
+ If you wish to use reset resources managed by the Broadcom
+ Reset Controller, say Y here. Otherwise, say N.
+
+config RESET_BRCMSTB_RESCAL
+ depends on ARCH_BCM283X
+ bool "Generic Rescal Reset controller driver for Broadcom"
+ help
+ Support rescal reset controller on Broadcom.
+ If you wish to use reset resources managed by the Broadcom
+ Reset Controller, say Y here. Otherwise, say N.
+
config RESET_UNIPHIER
bool "Reset controller driver for UniPhier SoCs"
depends on ARCH_UNIPHIER
@@ -91,6 +107,15 @@ config RESET_AST2600
Say Y if you want to control reset signals of different peripherals
through System Control Unit (SCU).
+config RESET_AST2700
+ bool "Reset controller driver for AST2700 SoCs"
+ depends on DM_RESET && ASPEED_AST2700
+ default y if ASPEED_AST2700
+ help
+ Support for reset controller on AST2700 SoC.
+ Say Y if you want to control reset signals of different peripherals
+ through System Control Unit (SCU).
+
config RESET_ROCKCHIP
bool "Reset controller driver for Rockchip SoCs"
depends on DM_RESET && ARCH_ROCKCHIP && CLK
@@ -100,6 +125,15 @@ config RESET_ROCKCHIP
though is that some reset signals, like I2C or MISC reset multiple
devices.
+config SPL_RESET_ROCKCHIP
+ bool "SPL reset controller driver for Rockchip SoCs"
+ depends on SPL_DM_RESET && ARCH_ROCKCHIP && SPL_CLK
+ default y
+ help
+ Support for the reset controller on Rockchip SoCs in SPL. Select this
+ if you observe any reset-related warnings or errors when booting SPL,
+ such as when using UFS storage
+
config RESET_HSDK
bool "Synopsys HSDK Reset Driver"
depends on DM_RESET && TARGET_HSDK
@@ -239,19 +273,11 @@ config RESET_AT91
config RESET_RZG2L_USBPHY_CTRL
bool "Enable support for Renesas RZ/G2L USB 2.0 PHY control"
- depends on DM_RESET
- select REGULATOR_RZG2L_USBPHY
+ depends on DM_RESET && REGULATOR_RZG2L_USBPHY
help
Enable support for controlling USB 2.0 PHY resets on the Renesas
RZ/G2L SoC. This is required for USB 2.0 functionality to work on this
SoC.
-config RESET_SPACEMIT_K1
- bool "Support for SPACEMIT's K1 Reset driver"
- depends on DM_RESET
- help
- Support for SPACEMIT's K1 Reset system. Basic Assert/Deassert
- is supported.
-
source "drivers/reset/stm32/Kconfig"
endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 088545c6473..384f4336331 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -13,10 +13,13 @@ obj-$(CONFIG_RESET_AIROHA) += reset-airoha.o
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
+obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
+obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_RESET_AST2500) += reset-ast2500.o
obj-$(CONFIG_RESET_AST2600) += reset-ast2600.o
-obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o rst-rk3506.o rst-rk3528.o rst-rk3576.o rst-rk3588.o
+obj-$(CONFIG_RESET_AST2700) += reset-ast2700.o
+obj-$(CONFIG_$(PHASE_)RESET_ROCKCHIP) += reset-rockchip.o rst-rk3506.o rst-rk3528.o rst-rk3576.o rst-rk3588.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_MEDIATEK) += reset-mediatek.o
@@ -34,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_RESET_SPACEMIT_K1) += reset-spacemit-k1.o
+obj-$(CONFIG_CLK_SPACEMIT_K1) += spacemit/
obj-$(CONFIG_ARCH_STM32) += stm32/
obj-$(CONFIG_ARCH_STM32MP) += stm32/
diff --git a/drivers/reset/reset-ast2500.c b/drivers/reset/reset-ast2500.c
index f3543fa8cc1..c85906bbeb5 100644
--- a/drivers/reset/reset-ast2500.c
+++ b/drivers/reset/reset-ast2500.c
@@ -77,10 +77,10 @@ static int ast2500_reset_probe(struct udevice *dev)
return rc;
}
- priv->scu = devfdt_get_addr_ptr(scu_dev);
+ priv->scu = dev_read_addr_ptr(scu_dev);
if (IS_ERR_OR_NULL(priv->scu)) {
debug("%s: invalid SCU base pointer\n", __func__);
- return PTR_ERR(priv->scu);
+ return -EINVAL;
}
return 0;
@@ -91,7 +91,7 @@ static const struct udevice_id ast2500_reset_ids[] = {
{ }
};
-struct reset_ops ast2500_reset_ops = {
+static const struct reset_ops ast2500_reset_ops = {
.rst_assert = ast2500_reset_assert,
.rst_deassert = ast2500_reset_deassert,
.rst_status = ast2500_reset_status,
diff --git a/drivers/reset/reset-ast2600.c b/drivers/reset/reset-ast2600.c
index ec7b9b6625d..71b6220225a 100644
--- a/drivers/reset/reset-ast2600.c
+++ b/drivers/reset/reset-ast2600.c
@@ -76,10 +76,10 @@ static int ast2600_reset_probe(struct udevice *dev)
return rc;
}
- priv->scu = devfdt_get_addr_ptr(scu_dev);
+ priv->scu = dev_read_addr_ptr(scu_dev);
if (IS_ERR_OR_NULL(priv->scu)) {
debug("%s: invalid SCU base pointer\n", __func__);
- return PTR_ERR(priv->scu);
+ return -EINVAL;
}
return 0;
@@ -90,7 +90,7 @@ static const struct udevice_id ast2600_reset_ids[] = {
{ }
};
-struct reset_ops ast2600_reset_ops = {
+static const struct reset_ops ast2600_reset_ops = {
.rst_assert = ast2600_reset_assert,
.rst_deassert = ast2600_reset_deassert,
.rst_status = ast2600_reset_status,
diff --git a/drivers/reset/reset-ast2700.c b/drivers/reset/reset-ast2700.c
new file mode 100644
index 00000000000..2dd9e36cc0a
--- /dev/null
+++ b/drivers/reset/reset-ast2700.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) ASPEED Technology Inc.
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <linux/err.h>
+#include <reset.h>
+#include <reset-uclass.h>
+
+/* Offset of the modrst register block within the SCU. */
+#define AST2700_RESET_OFFSET 0x200
+
+struct ast2700_reset_priv {
+ void __iomem *base;
+};
+
+static int ast2700_reset_assert(struct reset_ctl *reset_ctl)
+{
+ struct ast2700_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+
+ if (reset_ctl->id < 32)
+ writel(BIT(reset_ctl->id), priv->base);
+ else
+ writel(BIT(reset_ctl->id - 32), priv->base + 0x20);
+
+ return 0;
+}
+
+static int ast2700_reset_deassert(struct reset_ctl *reset_ctl)
+{
+ struct ast2700_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+
+ if (reset_ctl->id < 32)
+ writel(BIT(reset_ctl->id), priv->base + 0x04);
+ else
+ writel(BIT(reset_ctl->id - 32), priv->base + 0x24);
+
+ return 0;
+}
+
+static int ast2700_reset_status(struct reset_ctl *reset_ctl)
+{
+ struct ast2700_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+ int status;
+
+ if (reset_ctl->id < 32)
+ status = BIT(reset_ctl->id) & readl(priv->base);
+ else
+ status = BIT(reset_ctl->id - 32) & readl(priv->base + 0x20);
+
+ return !!status;
+}
+
+static int ast2700_reset_probe(struct udevice *dev)
+{
+ struct ast2700_reset_priv *priv = dev_get_priv(dev);
+ void __iomem *scu_base;
+
+ scu_base = dev_read_addr_ptr(dev);
+ if (!scu_base)
+ return -EINVAL;
+
+ priv->base = scu_base + AST2700_RESET_OFFSET;
+
+ return 0;
+}
+
+static const struct reset_ops ast2700_reset_ops = {
+ .rst_assert = ast2700_reset_assert,
+ .rst_deassert = ast2700_reset_deassert,
+ .rst_status = ast2700_reset_status,
+};
+
+U_BOOT_DRIVER(ast2700_reset) = {
+ .name = "ast2700_reset",
+ .id = UCLASS_RESET,
+ .probe = ast2700_reset_probe,
+ .ops = &ast2700_reset_ops,
+ .priv_auto = sizeof(struct ast2700_reset_priv),
+};
diff --git a/drivers/reset/reset-at91.c b/drivers/reset/reset-at91.c
index 165c87acdc4..ebbfae1469b 100644
--- a/drivers/reset/reset-at91.c
+++ b/drivers/reset/reset-at91.c
@@ -79,7 +79,7 @@ static int at91_rst_deassert(struct reset_ctl *reset_ctl)
return at91_rst_update(reset, reset_ctl->id, false);
}
-struct reset_ops at91_reset_ops = {
+static const struct reset_ops at91_reset_ops = {
.of_xlate = at91_reset_of_xlate,
.rst_assert = at91_rst_assert,
.rst_deassert = at91_rst_deassert,
diff --git a/drivers/reset/reset-bcm6345.c b/drivers/reset/reset-bcm6345.c
index 6f140574216..161d00d1b0c 100644
--- a/drivers/reset/reset-bcm6345.c
+++ b/drivers/reset/reset-bcm6345.c
@@ -49,7 +49,7 @@ static int bcm6345_reset_request(struct reset_ctl *rst)
return bcm6345_reset_assert(rst);
}
-struct reset_ops bcm6345_reset_reset_ops = {
+static const struct reset_ops bcm6345_reset_reset_ops = {
.request = bcm6345_reset_request,
.rst_assert = bcm6345_reset_assert,
.rst_deassert = bcm6345_reset_deassert,
diff --git a/drivers/reset/reset-brcmstb-rescal.c b/drivers/reset/reset-brcmstb-rescal.c
new file mode 100644
index 00000000000..fc8fcfa8b3f
--- /dev/null
+++ b/drivers/reset/reset-brcmstb-rescal.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Broadcom STB generic reset controller
+ *
+ * Copyright (C) 2024 EPAM Systems
+ * Moved from linux kernel:
+ * Copyright (C) 2018-2020 Broadcom
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <errno.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <log.h>
+#include <malloc.h>
+#include <reset-uclass.h>
+
+#define BRCM_RESCAL_START 0x0
+#define BRCM_RESCAL_START_BIT BIT(0)
+#define BRCM_RESCAL_CTRL 0x4
+#define BRCM_RESCAL_STATUS 0x8
+#define BRCM_RESCAL_STATUS_BIT BIT(0)
+
+struct brcm_rescal_reset {
+ void __iomem *base;
+};
+
+/* Also doubles a deassert */
+static int brcm_rescal_reset_set(struct reset_ctl *rst)
+{
+ struct brcm_rescal_reset *data = dev_get_priv(rst->dev);
+ void __iomem *base = data->base;
+ u32 reg;
+ int ret;
+
+ reg = readl(base + BRCM_RESCAL_START);
+ writel(reg | BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START);
+ reg = readl(base + BRCM_RESCAL_START);
+ if (!(reg & BRCM_RESCAL_START_BIT)) {
+ dev_err(rst->dev, "failed to start SATA/PCIe rescal\n");
+ return -EIO;
+ }
+
+ ret = readl_poll_timeout(base + BRCM_RESCAL_STATUS, reg,
+ (reg & BRCM_RESCAL_STATUS_BIT), 100);
+ if (ret) {
+ dev_err(rst->dev, "time out on SATA/PCIe rescal\n");
+ return ret;
+ }
+
+ reg = readl(base + BRCM_RESCAL_START);
+ writel(reg & ~BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START);
+
+ dev_dbg(rst->dev, "SATA/PCIe rescal success\n");
+ return 0;
+}
+
+/* A dummy function - deassert/reset does all the work */
+static int brcm_rescal_reset_assert(struct reset_ctl *rst)
+{
+ return 0;
+}
+
+static int brcm_rescal_reset_xlate(struct reset_ctl *reset_ctl,
+ struct ofnode_phandle_args *args)
+{
+ /* This is needed if #reset-cells == 0. */
+ return 0;
+}
+
+static const struct reset_ops brcm_rescal_reset_ops = {
+ .rst_deassert = brcm_rescal_reset_set,
+ .rst_assert = brcm_rescal_reset_assert,
+ .of_xlate = brcm_rescal_reset_xlate,
+};
+
+static int brcm_rescal_reset_probe(struct udevice *dev)
+{
+ struct brcm_rescal_reset *data = dev_get_priv(dev);
+
+ data->base = dev_remap_addr(dev);
+ if (!data->base)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct udevice_id brcm_rescal_reset_of_match[] = {
+ {.compatible = "brcm,bcm7216-pcie-sata-rescal"},
+ {},
+};
+
+U_BOOT_DRIVER(brcmstb_reset_rescal) = {
+ .name = "brcmstb-reset-rescal",
+ .id = UCLASS_RESET,
+ .of_match = brcm_rescal_reset_of_match,
+ .ops = &brcm_rescal_reset_ops,
+ .probe = brcm_rescal_reset_probe,
+ .priv_auto = sizeof(struct brcm_rescal_reset),
+};
diff --git a/drivers/reset/reset-brcmstb.c b/drivers/reset/reset-brcmstb.c
new file mode 100644
index 00000000000..7861f7c9baf
--- /dev/null
+++ b/drivers/reset/reset-brcmstb.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Broadcom STB generic reset controller
+ *
+ * Copyright (C) 2024 EPAM Systems
+ *
+ * Moved from linux kernel:
+ * Author: Florian Fainelli <[email protected]>
+ * Copyright (C) 2018 Broadcom
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <errno.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <log.h>
+#include <malloc.h>
+#include <reset-uclass.h>
+
+struct brcmstb_reset {
+ void __iomem *base;
+};
+
+#define SW_INIT_SET 0x00
+#define SW_INIT_CLEAR 0x04
+#define SW_INIT_STATUS 0x08
+
+#define SW_INIT_BIT(id) BIT((id) & 0x1f)
+#define SW_INIT_BANK(id) ((id) >> 5)
+
+#define usleep_range(a, b) udelay((b))
+
+/* A full bank contains extra registers that we are not utilizing but still
+ * qualify as a single bank.
+ */
+#define SW_INIT_BANK_SIZE 0x18
+
+static int brcmstb_reset_assert(struct reset_ctl *rst)
+{
+ unsigned int off = SW_INIT_BANK(rst->id) * SW_INIT_BANK_SIZE;
+ struct brcmstb_reset *priv = dev_get_priv(rst->dev);
+
+ writel_relaxed(SW_INIT_BIT(rst->id), priv->base + off + SW_INIT_SET);
+ return 0;
+}
+
+static int brcmstb_reset_deassert(struct reset_ctl *rst)
+{
+ unsigned int off = SW_INIT_BANK(rst->id) * SW_INIT_BANK_SIZE;
+ struct brcmstb_reset *priv = dev_get_priv(rst->dev);
+
+ writel_relaxed(SW_INIT_BIT(rst->id), priv->base + off + SW_INIT_CLEAR);
+ /* Maximum reset delay after de-asserting a line and seeing block
+ * operation is typically 14us for the worst case, build some slack
+ * here.
+ */
+ usleep_range(100, 200);
+ return 0;
+}
+
+static int brcmstb_reset_status(struct reset_ctl *rst)
+{
+ unsigned int off = SW_INIT_BANK(rst->id) * SW_INIT_BANK_SIZE;
+ struct brcmstb_reset *priv = dev_get_priv(rst->dev);
+
+ return readl_relaxed(priv->base + off + SW_INIT_STATUS) &
+ SW_INIT_BIT(rst->id);
+}
+
+struct reset_ops brcmstb_reset_reset_ops = {
+ .rst_assert = brcmstb_reset_assert,
+ .rst_deassert = brcmstb_reset_deassert,
+ .rst_status = brcmstb_reset_status};
+
+static int brcmstb_reset_probe(struct udevice *dev)
+{
+ struct brcmstb_reset *priv = dev_get_priv(dev);
+
+ priv->base = dev_remap_addr(dev);
+ if (!priv->base)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct udevice_id brcmstb_reset_ids[] = {
+ {.compatible = "brcm,brcmstb-reset"}, {/* sentinel */}};
+
+U_BOOT_DRIVER(brcmstb_reset) = {
+ .name = "brcmstb-reset",
+ .id = UCLASS_RESET,
+ .of_match = brcmstb_reset_ids,
+ .ops = &brcmstb_reset_reset_ops,
+ .probe = brcmstb_reset_probe,
+ .priv_auto = sizeof(struct brcmstb_reset),
+};
diff --git a/drivers/reset/reset-dra7.c b/drivers/reset/reset-dra7.c
index 2f0ec4c042f..6b570d87d23 100644
--- a/drivers/reset/reset-dra7.c
+++ b/drivers/reset/reset-dra7.c
@@ -51,7 +51,7 @@ static int dra7_reset_assert(struct reset_ctl *reset_ctl)
return 0;
}
-struct reset_ops dra7_reset_ops = {
+static const struct reset_ops dra7_reset_ops = {
.rst_assert = dra7_reset_assert,
.rst_deassert = dra7_reset_deassert,
};
diff --git a/drivers/reset/reset-mediatek.c b/drivers/reset/reset-mediatek.c
index 4b3afab92ea..66bcf7c29b6 100644
--- a/drivers/reset/reset-mediatek.c
+++ b/drivers/reset/reset-mediatek.c
@@ -47,7 +47,7 @@ static int mediatek_reset_deassert(struct reset_ctl *reset_ctl)
priv->regofs + ((id / 32) << 2), BIT(id % 32), 0);
}
-struct reset_ops mediatek_reset_ops = {
+static const struct reset_ops mediatek_reset_ops = {
.rst_assert = mediatek_reset_assert,
.rst_deassert = mediatek_reset_deassert,
};
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
index 6337cdaaffa..8c27563ce23 100644
--- a/drivers/reset/reset-meson.c
+++ b/drivers/reset/reset-meson.c
@@ -66,7 +66,7 @@ static int meson_reset_deassert(struct reset_ctl *reset_ctl)
return meson_reset_level(reset_ctl, false);
}
-struct reset_ops meson_reset_ops = {
+static const struct reset_ops meson_reset_ops = {
.request = meson_reset_request,
.rst_assert = meson_reset_assert,
.rst_deassert = meson_reset_deassert,
diff --git a/drivers/reset/reset-npcm.c b/drivers/reset/reset-npcm.c
index a3b85a42250..66b541f09e6 100644
--- a/drivers/reset/reset-npcm.c
+++ b/drivers/reset/reset-npcm.c
@@ -126,7 +126,7 @@ static const struct udevice_id npcm_reset_ids[] = {
{ }
};
-struct reset_ops npcm_reset_ops = {
+static const struct reset_ops npcm_reset_ops = {
.request = npcm_reset_request,
.rfree = npcm_reset_free,
.rst_assert = npcm_reset_assert,
diff --git a/drivers/reset/reset-raspberrypi.c b/drivers/reset/reset-raspberrypi.c
index 1792f0813f7..73acd301e3d 100644
--- a/drivers/reset/reset-raspberrypi.c
+++ b/drivers/reset/reset-raspberrypi.c
@@ -28,7 +28,7 @@ static int raspberrypi_reset_assert(struct reset_ctl *reset_ctl)
}
}
-struct reset_ops raspberrypi_reset_ops = {
+static const struct reset_ops raspberrypi_reset_ops = {
.request = raspberrypi_reset_request,
.rst_assert = raspberrypi_reset_assert,
};
diff --git a/drivers/reset/reset-spacemit-k1.c b/drivers/reset/reset-spacemit-k1.c
deleted file mode 100644
index 613e002fc4f..00000000000
--- a/drivers/reset/reset-spacemit-k1.c
+++ /dev/null
@@ -1,548 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2022 Spacemit Inc.
- * Copyright (C) 2025 Huan Zhou <[email protected]>
- */
-
-#include <asm/io.h>
-#include <config.h>
-#include <dm.h>
-#include <dm/device_compat.h>
-#include <dm/device-internal.h>
-#include <dm/lists.h>
-#include <dt-bindings/reset/spacemit-k1-reset.h>
-#include <linux/bitops.h>
-#include <reset-uclass.h>
-
-/* APBC register offset */
-#define APBC_UART1_CLK_RST 0x0
-#define APBC_UART2_CLK_RST 0x4
-#define APBC_GPIO_CLK_RST 0x8
-#define APBC_PWM0_CLK_RST 0xc
-#define APBC_PWM1_CLK_RST 0x10
-#define APBC_PWM2_CLK_RST 0x14
-#define APBC_PWM3_CLK_RST 0x18
-#define APBC_TWSI8_CLK_RST 0x20
-#define APBC_UART3_CLK_RST 0x24
-#define APBC_RTC_CLK_RST 0x28
-#define APBC_TWSI0_CLK_RST 0x2c
-#define APBC_TWSI1_CLK_RST 0x30
-#define APBC_TIMERS1_CLK_RST 0x34
-#define APBC_TWSI2_CLK_RST 0x38
-#define APBC_AIB_CLK_RST 0x3c
-#define APBC_TWSI4_CLK_RST 0x40
-#define APBC_TIMERS2_CLK_RST 0x44
-#define APBC_ONEWIRE_CLK_RST 0x48
-#define APBC_TWSI5_CLK_RST 0x4c
-#define APBC_DRO_CLK_RST 0x58
-#define APBC_IR_CLK_RST 0x5c
-#define APBC_TWSI6_CLK_RST 0x60
-#define APBC_TWSI7_CLK_RST 0x68
-#define APBC_TSEN_CLK_RST 0x6c
-
-#define APBC_UART4_CLK_RST 0x70
-#define APBC_UART5_CLK_RST 0x74
-#define APBC_UART6_CLK_RST 0x78
-#define APBC_SSP3_CLK_RST 0x7c
-
-#define APBC_SSPA0_CLK_RST 0x80
-#define APBC_SSPA1_CLK_RST 0x84
-
-#define APBC_IPC_AP2AUD_CLK_RST 0x90
-#define APBC_UART7_CLK_RST 0x94
-#define APBC_UART8_CLK_RST 0x98
-#define APBC_UART9_CLK_RST 0x9c
-
-#define APBC_CAN0_CLK_RST 0xa0
-#define APBC_PWM4_CLK_RST 0xa8
-#define APBC_PWM5_CLK_RST 0xac
-#define APBC_PWM6_CLK_RST 0xb0
-#define APBC_PWM7_CLK_RST 0xb4
-#define APBC_PWM8_CLK_RST 0xb8
-#define APBC_PWM9_CLK_RST 0xbc
-#define APBC_PWM10_CLK_RST 0xc0
-#define APBC_PWM11_CLK_RST 0xc4
-#define APBC_PWM12_CLK_RST 0xc8
-#define APBC_PWM13_CLK_RST 0xcc
-#define APBC_PWM14_CLK_RST 0xd0
-#define APBC_PWM15_CLK_RST 0xd4
-#define APBC_PWM16_CLK_RST 0xd8
-#define APBC_PWM17_CLK_RST 0xdc
-#define APBC_PWM18_CLK_RST 0xe0
-#define APBC_PWM19_CLK_RST 0xe4
-/* end of APBC register offset */
-
-/* MPMU register offset */
-#define MPMU_WDTPCR 0x200
-/* end of MPMU register offset */
-
-/* APMU register offset */
-#define APMU_JPG_CLK_RES_CTRL 0x20
-#define APMU_CSI_CCIC2_CLK_RES_CTRL 0x24
-#define APMU_ISP_CLK_RES_CTRL 0x38
-#define APMU_LCD_CLK_RES_CTRL1 0x44
-#define APMU_LCD_SPI_CLK_RES_CTRL 0x48
-#define APMU_LCD_CLK_RES_CTRL2 0x4c
-#define APMU_CCIC_CLK_RES_CTRL 0x50
-#define APMU_SDH0_CLK_RES_CTRL 0x54
-#define APMU_SDH1_CLK_RES_CTRL 0x58
-#define APMU_USB_CLK_RES_CTRL 0x5c
-#define APMU_QSPI_CLK_RES_CTRL 0x60
-#define APMU_USB_CLK_RES_CTRL 0x5c
-#define APMU_DMA_CLK_RES_CTRL 0x64
-#define APMU_AES_CLK_RES_CTRL 0x68
-#define APMU_VPU_CLK_RES_CTRL 0xa4
-#define APMU_GPU_CLK_RES_CTRL 0xcc
-#define APMU_SDH2_CLK_RES_CTRL 0xe0
-#define APMU_PMUA_MC_CTRL 0xe8
-#define APMU_PMU_CC2_AP 0x100
-#define APMU_PMUA_EM_CLK_RES_CTRL 0x104
-
-#define APMU_AUDIO_CLK_RES_CTRL 0x14c
-#define APMU_HDMI_CLK_RES_CTRL 0x1B8
-
-#define APMU_PCIE_CLK_RES_CTRL_0 0x3cc
-#define APMU_PCIE_CLK_RES_CTRL_1 0x3d4
-#define APMU_PCIE_CLK_RES_CTRL_2 0x3dc
-
-#define APMU_EMAC0_CLK_RES_CTRL 0x3e4
-#define APMU_EMAC1_CLK_RES_CTRL 0x3ec
-/* end of APMU register offset */
-
-/* APBC2 register offset */
-#define APBC2_UART1_CLK_RST 0x00
-#define APBC2_SSP2_CLK_RST 0x04
-#define APBC2_TWSI3_CLK_RST 0x08
-#define APBC2_RTC_CLK_RST 0x0c
-#define APBC2_TIMERS0_CLK_RST 0x10
-#define APBC2_KPC_CLK_RST 0x14
-#define APBC2_GPIO_CLK_RST 0x1c
-/* end of APBC2 register offset */
-
-enum spacemit_reset_base_type {
- RST_BASE_TYPE_MPMU = 0,
- RST_BASE_TYPE_APMU = 1,
- RST_BASE_TYPE_APBC = 2,
- RST_BASE_TYPE_APBS = 3,
- RST_BASE_TYPE_CIU = 4,
- RST_BASE_TYPE_DCIU = 5,
- RST_BASE_TYPE_DDRC = 6,
- RST_BASE_TYPE_AUDC = 7,
- RST_BASE_TYPE_APBC2 = 8,
-};
-
-struct spacemit_reset_signal {
- u32 offset;
- u32 mask;
- u32 deassert_val;
- u32 assert_val;
- enum spacemit_reset_base_type type;
-};
-
-struct spacemit_reset_base {
- void __iomem *mpmu_base;
- void __iomem *apmu_base;
- void __iomem *apbc_base;
- void __iomem *apbs_base;
- void __iomem *ciu_base;
- void __iomem *dciu_base;
- void __iomem *ddrc_base;
- void __iomem *audio_ctrl_base;
- void __iomem *apbc2_base;
-};
-
-struct spacemit_reset {
- struct spacemit_reset_base io_base;
- const struct spacemit_reset_signal *signals;
-};
-
-enum {
- RESET_TWSI6_SPL = 0,
- RESET_TWSI8_SPL,
- RESET_SDH_AXI_SPL,
- RESET_SDH0_SPL,
- RESET_USB_AXI_SPL,
- RESET_USBP1_AXI_SPL,
- RESET_USB3_0_SPL,
- RESET_QSPI_SPL,
- RESET_QSPI_BUS_SPL,
- RESET_AES_SPL,
- RESET_SDH2_SPL,
- RESET_NUMBER_SPL
-};
-
-static const struct spacemit_reset_signal
- k1_reset_signals[RESET_NUMBER] = {
- [RESET_UART1] = { APBC_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART2] = { APBC_UART2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_GPIO] = { APBC_GPIO_CLK_RST, BIT(2), 0,
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM0] = { APBC_PWM0_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM1] = { APBC_PWM1_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM2] = { APBC_PWM2_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM3] = { APBC_PWM3_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM4] = { APBC_PWM4_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM5] = { APBC_PWM5_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM6] = { APBC_PWM6_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM7] = { APBC_PWM7_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM8] = { APBC_PWM8_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM9] = { APBC_PWM9_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM10] = { APBC_PWM10_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM11] = { APBC_PWM11_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM12] = { APBC_PWM12_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM13] = { APBC_PWM13_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM14] = { APBC_PWM14_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM15] = { APBC_PWM15_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM16] = { APBC_PWM16_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM17] = { APBC_PWM17_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM18] = { APBC_PWM18_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM19] = { APBC_PWM19_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_SSP3] = { APBC_SSP3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART3] = { APBC_UART3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_RTC] = { APBC_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI0] = { APBC_TWSI0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TIMERS1] = { APBC_TIMERS1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_AIB] = { APBC_AIB_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TIMERS2] = { APBC_TIMERS2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_ONEWIRE] = { APBC_ONEWIRE_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_SSPA0] = { APBC_SSPA0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_SSPA1] = { APBC_SSPA1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_DRO] = { APBC_DRO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_IR] = { APBC_IR_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI1] = { APBC_TWSI1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TSEN] = { APBC_TSEN_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI2] = { APBC_TWSI2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI4] = { APBC_TWSI4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI5] = { APBC_TWSI5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI6] = { APBC_TWSI6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI7] = { APBC_TWSI7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI8] = { APBC_TWSI8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_IPC_AP2AUD] = { APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART4] = { APBC_UART4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART5] = { APBC_UART5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART6] = { APBC_UART6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART7] = { APBC_UART7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART8] = { APBC_UART8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART9] = { APBC_UART9_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_CAN0] = { APBC_CAN0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- /* MPMU */
- [RESET_WDT] = { MPMU_WDTPCR, BIT(2), 0, BIT(2), RST_BASE_TYPE_MPMU },
- /* APMU */
- [RESET_JPG] = { APMU_JPG_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_CSI] = { APMU_CSI_CCIC2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_CCIC2_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL,
- BIT(2),
- BIT(2),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_CCIC3_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL,
- BIT(29),
- BIT(29),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_ISP] = { APMU_ISP_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_ISP_AHB] = { APMU_ISP_CLK_RES_CTRL, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU },
- [RESET_ISP_CI] = { APMU_ISP_CLK_RES_CTRL, BIT(16), BIT(16), 0, RST_BASE_TYPE_APMU },
- [RESET_ISP_CPP] = { APMU_ISP_CLK_RES_CTRL, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU },
- [RESET_LCD] = { APMU_LCD_CLK_RES_CTRL1, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
- [RESET_DSI_ESC] = { APMU_LCD_CLK_RES_CTRL1, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU },
- [RESET_V2D] = { APMU_LCD_CLK_RES_CTRL1, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU },
- [RESET_MIPI] = { APMU_LCD_CLK_RES_CTRL1, BIT(15), BIT(15), 0, RST_BASE_TYPE_APMU },
- [RESET_LCD_SPI] = { APMU_LCD_SPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_LCD_SPI_BUS] = { APMU_LCD_SPI_CLK_RES_CTRL,
- BIT(4),
- BIT(4),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_LCD_SPI_HBUS] = { APMU_LCD_SPI_CLK_RES_CTRL,
- BIT(2),
- BIT(2),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_LCD_MCLK] = { APMU_LCD_CLK_RES_CTRL2, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU },
- [RESET_CCIC_4X] = { APMU_CCIC_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_CCIC1_PHY] = { APMU_CCIC_CLK_RES_CTRL, BIT(2), BIT(2), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH_AXI] = { APMU_SDH0_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH0] = { APMU_SDH0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH1] = { APMU_SDH1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_USB_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_USBP1_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
- [RESET_USB3_0] = { APMU_USB_CLK_RES_CTRL,
- BIT(9) | BIT(10) | BIT(11),
- BIT(9) | BIT(10) | BIT(11),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_QSPI] = { APMU_QSPI_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_QSPI_BUS] = { APMU_QSPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_DMA] = { APMU_DMA_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_AES] = { APMU_AES_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
- [RESET_VPU] = { APMU_VPU_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_GPU] = { APMU_GPU_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH2] = { APMU_SDH2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_MC] = { APMU_PMUA_MC_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_EM_AXI] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_EM] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_AUDIO_SYS] = { APMU_AUDIO_CLK_RES_CTRL,
- BIT(0) | BIT(2) | BIT(3),
- BIT(0) | BIT(2) | BIT(3),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_HDMI] = { APMU_HDMI_CLK_RES_CTRL, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU },
- [RESET_PCIE0] = { APMU_PCIE_CLK_RES_CTRL_0,
- BIT(3) | BIT(4) | BIT(5) | BIT(8),
- BIT(3) | BIT(4) | BIT(5),
- BIT(8),
- RST_BASE_TYPE_APMU },
- [RESET_PCIE1] = { APMU_PCIE_CLK_RES_CTRL_1,
- BIT(3) | BIT(4) | BIT(5) | BIT(8),
- BIT(3) | BIT(4) | BIT(5),
- BIT(8),
- RST_BASE_TYPE_APMU },
- [RESET_PCIE2] = { APMU_PCIE_CLK_RES_CTRL_2, 0x138, 0x38, 0x100, RST_BASE_TYPE_APMU },
- [RESET_EMAC0] = { APMU_EMAC0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_EMAC1] = { APMU_EMAC1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_SEC_UART1] = { APBC2_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_SSP2] = { APBC2_SSP2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_TWSI3] = { APBC2_TWSI3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_RTC] = { APBC2_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_TIMERS0] = { APBC2_TIMERS0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_KPC] = { APBC2_KPC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_GPIO] = { APBC2_GPIO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- };
-
-static u32 spacemit_reset_read(struct spacemit_reset *reset, u32 id)
-{
- void __iomem *base;
-
- switch (reset->signals[id].type) {
- case RST_BASE_TYPE_APMU:
- base = reset->io_base.apmu_base;
- break;
- case RST_BASE_TYPE_APBC:
- base = reset->io_base.apbc_base;
- break;
- default:
- base = reset->io_base.apbc_base;
- break;
- }
-
- return readl(base + reset->signals[id].offset);
-}
-
-static void spacemit_reset_write(struct spacemit_reset *reset, u32 value, u32 id)
-{
- void __iomem *base;
-
- switch (reset->signals[id].type) {
- case RST_BASE_TYPE_APMU:
- base = reset->io_base.apmu_base;
- break;
- case RST_BASE_TYPE_APBC:
- base = reset->io_base.apbc_base;
- break;
- default:
- base = reset->io_base.apbc_base;
- break;
- }
-
- writel(value, base + reset->signals[id].offset);
-}
-
-static void spacemit_reset_set(struct reset_ctl *rst, u32 id, bool assert)
-{
- u32 value;
- struct spacemit_reset *reset = dev_get_priv(rst->dev);
-
- value = spacemit_reset_read(reset, id);
-
- if (assert) {
- value &= ~reset->signals[id].mask;
- value |= reset->signals[id].assert_val;
- } else {
- value &= ~reset->signals[id].mask;
- value |= reset->signals[id].deassert_val;
- }
-
- spacemit_reset_write(reset, value, id);
-}
-
-static int spacemit_reset_update(struct reset_ctl *rst, bool assert)
-{
- if (rst->id < RESET_UART1 || rst->id >= RESET_NUMBER)
- return 0;
-
- /* can not write to twsi8 */
- if (rst->id == RESET_TWSI8)
- return 0;
-
- spacemit_reset_set(rst, rst->id, assert);
- return 0;
-}
-
-static int spacemit_reset_assert(struct reset_ctl *rst)
-{
- return spacemit_reset_update(rst, true);
-}
-
-static int spacemit_reset_deassert(struct reset_ctl *rst)
-{
- return spacemit_reset_update(rst, false);
-}
-
-static int spacemit_k1_reset_probe(struct udevice *dev)
-{
- struct spacemit_reset *reset = dev_get_priv(dev);
-
- reset->io_base.mpmu_base = (void *)dev_remap_addr_index(dev, 0);
- if (!reset->io_base.mpmu_base) {
- pr_err("failed to map mpmu registers\n");
- goto out;
- }
-
- reset->io_base.apmu_base = (void *)dev_remap_addr_index(dev, 1);
- if (!reset->io_base.apmu_base) {
- pr_err("failed to map apmu registers\n");
- goto out;
- }
-
- reset->io_base.apbc_base = (void *)dev_remap_addr_index(dev, 2);
- if (!reset->io_base.apbc_base) {
- pr_err("failed to map apbc registers\n");
- goto out;
- }
-
- reset->io_base.apbs_base = (void *)dev_remap_addr_index(dev, 3);
- if (!reset->io_base.apbs_base) {
- pr_err("failed to map apbs registers\n");
- goto out;
- }
-
- reset->io_base.ciu_base = (void *)dev_remap_addr_index(dev, 4);
- if (!reset->io_base.ciu_base) {
- pr_err("failed to map ciu registers\n");
- goto out;
- }
-
- reset->io_base.dciu_base = (void *)dev_remap_addr_index(dev, 5);
- if (!reset->io_base.dciu_base) {
- pr_err("failed to map dragon ciu registers\n");
- goto out;
- }
-
- reset->io_base.ddrc_base = (void *)dev_remap_addr_index(dev, 6);
- if (!reset->io_base.ddrc_base) {
- pr_err("failed to map ddrc registers\n");
- goto out;
- }
-
- reset->io_base.apbc2_base = (void *)dev_remap_addr_index(dev, 7);
- if (!reset->io_base.apbc2_base) {
- pr_err("failed to map apbc2 registers\n");
- goto out;
- }
-
- reset->signals = k1_reset_signals;
-
-out:
- return 0;
-}
-
-const struct reset_ops k1_reset_ops = {
- .rst_assert = spacemit_reset_assert,
- .rst_deassert = spacemit_reset_deassert,
-};
-
-static const struct udevice_id k1_reset_ids[] = {
- { .compatible = "spacemit,k1-reset", },
- {},
-};
-
-U_BOOT_DRIVER(k1_reset) = {
- .name = "spacemit,k1-reset",
- .id = UCLASS_RESET,
- .ops = &k1_reset_ops,
- .of_match = k1_reset_ids,
- .probe = spacemit_k1_reset_probe,
- .priv_auto = sizeof(struct spacemit_reset),
-};
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
index fd47e1f9e37..6195edd5b2f 100644
--- a/drivers/reset/reset-sunxi.c
+++ b/drivers/reset/reset-sunxi.c
@@ -67,7 +67,7 @@ static int sunxi_reset_deassert(struct reset_ctl *reset_ctl)
return sunxi_set_reset(reset_ctl, true);
}
-struct reset_ops sunxi_reset_ops = {
+static const struct reset_ops sunxi_reset_ops = {
.request = sunxi_reset_request,
.rst_assert = sunxi_reset_assert,
.rst_deassert = sunxi_reset_deassert,
diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index fe4cebf54f1..c199e3e5da7 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -13,6 +13,7 @@
#include <reset-uclass.h>
#include <dm/devres.h>
#include <dm/lists.h>
+#include <linux/delay.h>
static inline struct reset_ops *reset_dev_ops(struct udevice *dev)
{
@@ -225,6 +226,39 @@ int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
return 0;
}
+int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us)
+{
+ struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
+ int ret;
+
+ debug("%s(reset_ctl=%p, delay_us=%lu)\n", __func__, reset_ctl,
+ delay_us);
+
+ if (ops->rst_reset)
+ return ops->rst_reset(reset_ctl, delay_us);
+
+ ret = reset_assert(reset_ctl);
+ if (ret < 0)
+ return ret;
+
+ udelay(delay_us);
+
+ return reset_deassert(reset_ctl);
+}
+
+int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us)
+{
+ int i, ret;
+
+ for (i = 0; i < bulk->count; i++) {
+ ret = reset_reset(&bulk->resets[i], delay_us);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
int reset_status(struct reset_ctl *reset_ctl)
{
struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c
index d04e8eef3bb..2b58f3a75b4 100644
--- a/drivers/reset/reset-zynqmp.c
+++ b/drivers/reset/reset-zynqmp.c
@@ -45,6 +45,16 @@ static int zynqmp_reset_deassert(struct reset_ctl *rst)
PM_RESET_ACTION_RELEASE);
}
+static int zynqmp_reset_reset(struct reset_ctl *rst, ulong delay_us)
+{
+ struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
+
+ dev_dbg(rst->dev, "%s(rst=%p) (id=%lu)\n", __func__, rst, rst->id);
+
+ return zynqmp_pm_reset_assert(priv->reset_id + rst->id,
+ PM_RESET_ACTION_PULSE);
+}
+
static int zynqmp_reset_request(struct reset_ctl *rst)
{
struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
@@ -74,6 +84,7 @@ const struct reset_ops zynqmp_reset_ops = {
.request = zynqmp_reset_request,
.rst_assert = zynqmp_reset_assert,
.rst_deassert = zynqmp_reset_deassert,
+ .rst_reset = zynqmp_reset_reset,
};
static const struct udevice_id zynqmp_reset_ids[] = {
diff --git a/drivers/reset/sandbox-reset-test.c b/drivers/reset/sandbox-reset-test.c
index dfacb764bc7..64c205596c5 100644
--- a/drivers/reset/sandbox-reset-test.c
+++ b/drivers/reset/sandbox-reset-test.c
@@ -96,6 +96,20 @@ int sandbox_reset_test_deassert_bulk(struct udevice *dev)
return reset_deassert_bulk(sbrt->bulkp);
}
+int sandbox_reset_test_reset(struct udevice *dev)
+{
+ struct sandbox_reset_test *sbrt = dev_get_priv(dev);
+
+ return reset_reset(sbrt->ctlp, 0);
+}
+
+int sandbox_reset_test_reset_bulk(struct udevice *dev)
+{
+ struct sandbox_reset_test *sbrt = dev_get_priv(dev);
+
+ return reset_reset_bulk(sbrt->bulkp, 0);
+}
+
int sandbox_reset_test_free(struct udevice *dev)
{
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
diff --git a/drivers/reset/sandbox-reset.c b/drivers/reset/sandbox-reset.c
index adf9eedcba6..12812f0f340 100644
--- a/drivers/reset/sandbox-reset.c
+++ b/drivers/reset/sandbox-reset.c
@@ -9,12 +9,14 @@
#include <reset-uclass.h>
#include <asm/io.h>
#include <asm/reset.h>
+#include <linux/delay.h>
#define SANDBOX_RESET_SIGNALS 101
struct sandbox_reset_signal {
bool asserted;
bool requested;
+ int reset_count;
};
struct sandbox_reset {
@@ -31,6 +33,7 @@ static int sandbox_reset_request(struct reset_ctl *reset_ctl)
return -EINVAL;
sbr->signals[reset_ctl->id].requested = true;
+ sbr->signals[reset_ctl->id].reset_count = 0;
return 0;
}
@@ -66,6 +69,21 @@ static int sandbox_reset_deassert(struct reset_ctl *reset_ctl)
return 0;
}
+static int sandbox_reset_reset(struct reset_ctl *reset_ctl, ulong delay_us)
+{
+ struct sandbox_reset *sbr = dev_get_priv(reset_ctl->dev);
+
+ debug("%s(reset_ctl=%p, delay_us=%lu)\n", __func__, reset_ctl,
+ delay_us);
+
+ sbr->signals[reset_ctl->id].asserted = true;
+ udelay(delay_us);
+ sbr->signals[reset_ctl->id].asserted = false;
+ sbr->signals[reset_ctl->id].reset_count++;
+
+ return 0;
+}
+
static int sandbox_reset_bind(struct udevice *dev)
{
debug("%s(dev=%p)\n", __func__, dev);
@@ -85,11 +103,12 @@ static const struct udevice_id sandbox_reset_ids[] = {
{ }
};
-struct reset_ops sandbox_reset_reset_ops = {
+static const struct reset_ops sandbox_reset_reset_ops = {
.request = sandbox_reset_request,
.rfree = sandbox_reset_free,
.rst_assert = sandbox_reset_assert,
.rst_deassert = sandbox_reset_deassert,
+ .rst_reset = sandbox_reset_reset,
};
U_BOOT_DRIVER(sandbox_reset) = {
@@ -102,6 +121,33 @@ U_BOOT_DRIVER(sandbox_reset) = {
.ops = &sandbox_reset_reset_ops,
};
+/*
+ * Second sandbox reset controller for tests: same assert/deassert
+ * behaviour as sandbox_reset, but no rst_reset so reset_reset() uses
+ * the core assert / udelay / deassert fallback (reset_count never bumps).
+ */
+static const struct udevice_id sandbox_reset_fallback_ids[] = {
+ { .compatible = "sandbox,reset-ctl-fallback-only" },
+ { }
+};
+
+static const struct reset_ops sandbox_reset_fallback_reset_ops = {
+ .request = sandbox_reset_request,
+ .rfree = sandbox_reset_free,
+ .rst_assert = sandbox_reset_assert,
+ .rst_deassert = sandbox_reset_deassert,
+};
+
+U_BOOT_DRIVER(sandbox_reset_fallback) = {
+ .name = "sandbox_reset_fallback",
+ .id = UCLASS_RESET,
+ .of_match = sandbox_reset_fallback_ids,
+ .bind = sandbox_reset_bind,
+ .probe = sandbox_reset_probe,
+ .priv_auto = sizeof(struct sandbox_reset),
+ .ops = &sandbox_reset_fallback_reset_ops,
+};
+
int sandbox_reset_query(struct udevice *dev, unsigned long id)
{
struct sandbox_reset *sbr = dev_get_priv(dev);
@@ -125,3 +171,15 @@ int sandbox_reset_is_requested(struct udevice *dev, unsigned long id)
return sbr->signals[id].requested;
}
+
+int sandbox_reset_get_count(struct udevice *dev, unsigned long id)
+{
+ struct sandbox_reset *sbr = dev_get_priv(dev);
+
+ debug("%s(dev=%p, id=%ld)\n", __func__, dev, id);
+
+ if (id >= SANDBOX_RESET_SIGNALS)
+ return -EINVAL;
+
+ return sbr->signals[id].reset_count;
+}
diff --git a/drivers/reset/spacemit/Makefile b/drivers/reset/spacemit/Makefile
new file mode 100644
index 00000000000..16722c68954
--- /dev/null
+++ b/drivers/reset/spacemit/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# SpacemiT reset drivers
+
+obj-y += reset-spacemit-k1.o
diff --git a/drivers/reset/spacemit/reset-spacemit-k1.c b/drivers/reset/spacemit/reset-spacemit-k1.c
new file mode 100644
index 00000000000..129e1cc96f1
--- /dev/null
+++ b/drivers/reset/spacemit/reset-spacemit-k1.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SpacemiT K1 reset driver (syscon-bound).
+ *
+ * Copyright (C) 2022 Spacemit Inc.
+ * Copyright (C) 2025 Huan Zhou <[email protected]>
+ * 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;
+};
+
+#define RESET_DATA(o, a, d) { \
+ .offset = (o), .assert_mask = (a), .deassert_mask = (d) \
+}
+
+static const struct spacemit_k1_reset_data k1_mpmu_resets[] = {
+ [RESET_WDT] = RESET_DATA(MPMU_WDTPCR, BIT(2), 0),
+};
+
+static const struct spacemit_k1_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),
+ [RESET_UART4] = RESET_DATA(APBC_UART4_CLK_RST, BIT(2), 0),
+ [RESET_UART5] = RESET_DATA(APBC_UART5_CLK_RST, BIT(2), 0),
+ [RESET_UART6] = RESET_DATA(APBC_UART6_CLK_RST, BIT(2), 0),
+ [RESET_UART7] = RESET_DATA(APBC_UART7_CLK_RST, BIT(2), 0),
+ [RESET_UART8] = RESET_DATA(APBC_UART8_CLK_RST, BIT(2), 0),
+ [RESET_UART9] = RESET_DATA(APBC_UART9_CLK_RST, BIT(2), 0),
+ [RESET_GPIO] = RESET_DATA(APBC_GPIO_CLK_RST, BIT(2), 0),
+ [RESET_PWM0] = RESET_DATA(APBC_PWM0_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM1] = RESET_DATA(APBC_PWM1_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM2] = RESET_DATA(APBC_PWM2_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM3] = RESET_DATA(APBC_PWM3_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM4] = RESET_DATA(APBC_PWM4_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM5] = RESET_DATA(APBC_PWM5_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM6] = RESET_DATA(APBC_PWM6_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM7] = RESET_DATA(APBC_PWM7_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM8] = RESET_DATA(APBC_PWM8_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM9] = RESET_DATA(APBC_PWM9_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM10] = RESET_DATA(APBC_PWM10_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM11] = RESET_DATA(APBC_PWM11_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM12] = RESET_DATA(APBC_PWM12_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM13] = RESET_DATA(APBC_PWM13_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM14] = RESET_DATA(APBC_PWM14_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM15] = RESET_DATA(APBC_PWM15_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM16] = RESET_DATA(APBC_PWM16_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM17] = RESET_DATA(APBC_PWM17_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM18] = RESET_DATA(APBC_PWM18_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM19] = RESET_DATA(APBC_PWM19_CLK_RST, BIT(2), BIT(0)),
+ [RESET_SSP3] = RESET_DATA(APBC_SSP3_CLK_RST, BIT(2), 0),
+ [RESET_RTC] = RESET_DATA(APBC_RTC_CLK_RST, BIT(2), 0),
+ [RESET_TWSI0] = RESET_DATA(APBC_TWSI0_CLK_RST, BIT(2), 0),
+ [RESET_TWSI1] = RESET_DATA(APBC_TWSI1_CLK_RST, BIT(2), 0),
+ [RESET_TWSI2] = RESET_DATA(APBC_TWSI2_CLK_RST, BIT(2), 0),
+ [RESET_TWSI4] = RESET_DATA(APBC_TWSI4_CLK_RST, BIT(2), 0),
+ [RESET_TWSI5] = RESET_DATA(APBC_TWSI5_CLK_RST, BIT(2), 0),
+ [RESET_TWSI6] = RESET_DATA(APBC_TWSI6_CLK_RST, BIT(2), 0),
+ [RESET_TWSI7] = RESET_DATA(APBC_TWSI7_CLK_RST, BIT(2), 0),
+ [RESET_TWSI8] = RESET_DATA(APBC_TWSI8_CLK_RST, BIT(2), 0),
+ [RESET_TIMERS1] = RESET_DATA(APBC_TIMERS1_CLK_RST, BIT(2), 0),
+ [RESET_TIMERS2] = RESET_DATA(APBC_TIMERS2_CLK_RST, BIT(2), 0),
+ [RESET_AIB] = RESET_DATA(APBC_AIB_CLK_RST, BIT(2), 0),
+ [RESET_ONEWIRE] = RESET_DATA(APBC_ONEWIRE_CLK_RST, BIT(2), 0),
+ [RESET_SSPA0] = RESET_DATA(APBC_SSPA0_CLK_RST, BIT(2), 0),
+ [RESET_SSPA1] = RESET_DATA(APBC_SSPA1_CLK_RST, BIT(2), 0),
+ [RESET_DRO] = RESET_DATA(APBC_DRO_CLK_RST, BIT(2), 0),
+ [RESET_IR] = RESET_DATA(APBC_IR_CLK_RST, BIT(2), 0),
+ [RESET_TSEN] = RESET_DATA(APBC_TSEN_CLK_RST, BIT(2), 0),
+ [RESET_IPC_AP2AUD] = RESET_DATA(APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0),
+ [RESET_CAN0] = RESET_DATA(APBC_CAN0_CLK_RST, BIT(2), 0),
+};
+
+static const struct spacemit_k1_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)),
+ [RESET_SDH0] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_SDH1] = RESET_DATA(APMU_SDH1_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_SDH2] = RESET_DATA(APMU_SDH2_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_USBP1_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(4)),
+ [RESET_USB_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_USB30_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(9)),
+ [RESET_USB30_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(10)),
+ [RESET_USB30_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(11)),
+ [RESET_QSPI] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_QSPI_BUS] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_DMA] = RESET_DATA(APMU_DMA_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_AES] = RESET_DATA(APMU_AES_CLK_RES_CTRL, 0, BIT(4)),
+ [RESET_VPU] = RESET_DATA(APMU_VPU_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_GPU] = RESET_DATA(APMU_GPU_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_EMMC] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_EMMC_X] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_AUDIO_SYS] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_AUDIO_MCU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_AUDIO_APMU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(3)),
+ [RESET_HDMI] = RESET_DATA(APMU_HDMI_CLK_RES_CTRL, 0, BIT(9)),
+ [RESET_PCIE0_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(3)),
+ [RESET_PCIE0_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(4)),
+ [RESET_PCIE0_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(5)),
+ [RESET_PCIE0_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, BIT(8), 0),
+ [RESET_PCIE1_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(3)),
+ [RESET_PCIE1_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(4)),
+ [RESET_PCIE1_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(5)),
+ [RESET_PCIE1_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, BIT(8), 0),
+ [RESET_PCIE2_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(3)),
+ [RESET_PCIE2_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(4)),
+ [RESET_PCIE2_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(5)),
+ [RESET_PCIE2_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, BIT(8), 0),
+ [RESET_EMAC0] = RESET_DATA(APMU_EMAC0_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_EMAC1] = RESET_DATA(APMU_EMAC1_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_JPG] = RESET_DATA(APMU_JPG_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_CCIC2PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_CCIC3PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(29)),
+ [RESET_CSI] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_ISP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_ISP_CPP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(27)),
+ [RESET_ISP_BUS] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(3)),
+ [RESET_ISP_CI] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(16)),
+ [RESET_DPU_MCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL2, 0, BIT(9)),
+ [RESET_DPU_ESC] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(3)),
+ [RESET_DPU_HCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(4)),
+ [RESET_DPU_SPIBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(4)),
+ [RESET_DPU_SPI_HBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_V2D] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(27)),
+ [RESET_MIPI] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(15)),
+ [RESET_MC] = RESET_DATA(APMU_PMUA_MC_CTRL, 0, BIT(0)),
+};
+
+static const struct spacemit_k1_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),
+ [RESET_APBC2_RTC] = RESET_DATA(APBC2_RTC_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_TIMERS0] = RESET_DATA(APBC2_TIMERS0_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_KPC] = RESET_DATA(APBC2_KPC_CLK_RST, BIT(2), 0),
+ [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),
+ .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;
+ size_t table_size;
+ int ret;
+
+ switch (syscon) {
+ case SPACEMIT_K1_RESET_MPMU:
+ table = k1_mpmu_resets;
+ table_size = ARRAY_SIZE(k1_mpmu_resets);
+ break;
+ case SPACEMIT_K1_RESET_APMU:
+ table = k1_apmu_resets;
+ table_size = ARRAY_SIZE(k1_apmu_resets);
+ break;
+ case SPACEMIT_K1_RESET_APBC:
+ table = k1_apbc_resets;
+ table_size = ARRAY_SIZE(k1_apbc_resets);
+ break;
+ case SPACEMIT_K1_RESET_APBC2:
+ table = k1_apbc2_resets;
+ table_size = ARRAY_SIZE(k1_apbc2_resets);
+ break;
+ default:
+ 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;
+}
diff --git a/drivers/reset/sti-reset.c b/drivers/reset/sti-reset.c
index 412a0c5b452..37a37a72fd3 100644
--- a/drivers/reset/sti-reset.c
+++ b/drivers/reset/sti-reset.c
@@ -290,7 +290,7 @@ static int sti_reset_deassert(struct reset_ctl *reset_ctl)
return sti_reset_program_hw(reset_ctl, false);
}
-struct reset_ops sti_reset_ops = {
+static const struct reset_ops sti_reset_ops = {
.rst_assert = sti_reset_assert,
.rst_deassert = sti_reset_deassert,
};
diff --git a/drivers/reset/stm32/stm32-reset-mp21.c b/drivers/reset/stm32/stm32-reset-mp21.c
index 7d169d7582f..0e92b0f5d5d 100644
--- a/drivers/reset/stm32/stm32-reset-mp21.c
+++ b/drivers/reset/stm32/stm32-reset-mp21.c
@@ -5,7 +5,7 @@
*/
#include <dm.h>
-#include <stm32-reset-core.h>
+#include "stm32-reset-core.h"
#include <stm32mp21_rcc.h>
#include <dt-bindings/reset/st,stm32mp21-rcc.h>
diff --git a/drivers/reset/tegra-car-reset.c b/drivers/reset/tegra-car-reset.c
index e3ecc8d3735..63f148cf3d9 100644
--- a/drivers/reset/tegra-car-reset.c
+++ b/drivers/reset/tegra-car-reset.c
@@ -42,7 +42,7 @@ static int tegra_car_reset_deassert(struct reset_ctl *reset_ctl)
return 0;
}
-struct reset_ops tegra_car_reset_ops = {
+static const struct reset_ops tegra_car_reset_ops = {
.request = tegra_car_reset_request,
.rst_assert = tegra_car_reset_assert,
.rst_deassert = tegra_car_reset_deassert,
diff --git a/drivers/reset/tegra186-reset.c b/drivers/reset/tegra186-reset.c
index 89624227c29..1d8f40acaef 100644
--- a/drivers/reset/tegra186-reset.c
+++ b/drivers/reset/tegra186-reset.c
@@ -43,7 +43,7 @@ static int tegra186_reset_deassert(struct reset_ctl *reset_ctl)
return tegra186_reset_common(reset_ctl, CMD_RESET_DEASSERT);
}
-struct reset_ops tegra186_reset_ops = {
+static const struct reset_ops tegra186_reset_ops = {
.rst_assert = tegra186_reset_assert,
.rst_deassert = tegra186_reset_deassert,
};