summaryrefslogtreecommitdiff
path: root/drivers/reset
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2026-07-06 18:26:12 -0600
committerTom Rini <trini@konsulko.com>2026-07-06 18:26:12 -0600
commitee5d46b45ec0c63f8f9dd1e816e0dac3452ccc3d (patch)
tree800cd9e204ca027144070101884c0d5d3c00130f /drivers/reset
parentece349ade2973e220f524ce59e59711cc919263f (diff)
parenta18265f1ccb7a272721ed4286ed3b5a6182ff424 (diff)
downloadu-boot-master.tar.gz
u-boot-master.zip
Merge branch 'next'HEADmasterWIP/06Jul2026
Diffstat (limited to 'drivers/reset')
-rw-r--r--drivers/reset/Kconfig9
-rw-r--r--drivers/reset/Makefile1
-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-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-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/sti-reset.c2
-rw-r--r--drivers/reset/tegra-car-reset.c2
-rw-r--r--drivers/reset/tegra186-reset.c2
20 files changed, 227 insertions, 18 deletions
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-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-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-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/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/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,
};