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]> --- drivers/reset/Kconfig | 9 +++++ drivers/reset/Makefile | 1 + drivers/reset/reset-ast2700.c | 82 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index ebf484d9df4..0af5d4b104e 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -91,6 +91,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 088545c6473..e722b940e9c 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.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_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

