Add reset controller driver for the dual-die AST2700 SoC. The
controller manages module-level reset signals via the modrst
register block at offset 0x200 within each SCU.

Signed-off-by: Ryan Chen <[email protected]>
---
 MAINTAINERS                   |  2 +-
 drivers/reset/Kconfig         |  9 +++++
 drivers/reset/Makefile        |  1 +
 drivers/reset/reset-ast2700.c | 82 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 41059979f30..6a633df499d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -222,7 +222,7 @@ F:  drivers/net/ftgmac100.[ch]
 F:     drivers/pinctrl/aspeed/
 F:     drivers/pwm/pwm-aspeed.c
 F:     drivers/ram/aspeed/
-F:     drivers/reset/reset-ast2500.c
+F:     drivers/reset/reset-ast*.c
 F:     drivers/watchdog/ast_wdt.c
 N:     aspeed
 N:     ast2700
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index e7c0870c918..c851354c7a5 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -107,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
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 2c83f858895..3fce96509cd 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -18,6 +18,7 @@ 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_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
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),
+};

-- 
2.34.1

Reply via email to