diff options
| author | Tom Rini <trini@konsulko.com> | 2026-07-06 18:26:12 -0600 |
|---|---|---|
| committer | Tom Rini <trini@konsulko.com> | 2026-07-06 18:26:12 -0600 |
| commit | ee5d46b45ec0c63f8f9dd1e816e0dac3452ccc3d (patch) | |
| tree | 800cd9e204ca027144070101884c0d5d3c00130f /drivers/reset | |
| parent | ece349ade2973e220f524ce59e59711cc919263f (diff) | |
| parent | a18265f1ccb7a272721ed4286ed3b5a6182ff424 (diff) | |
| download | u-boot-master.tar.gz u-boot-master.zip | |
Merge branch 'next'HEADmasterWIP/06Jul2026
Diffstat (limited to 'drivers/reset')
| -rw-r--r-- | drivers/reset/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/reset/Makefile | 1 | ||||
| -rw-r--r-- | drivers/reset/reset-ast2500.c | 6 | ||||
| -rw-r--r-- | drivers/reset/reset-ast2600.c | 6 | ||||
| -rw-r--r-- | drivers/reset/reset-ast2700.c | 82 | ||||
| -rw-r--r-- | drivers/reset/reset-at91.c | 2 | ||||
| -rw-r--r-- | drivers/reset/reset-bcm6345.c | 2 | ||||
| -rw-r--r-- | drivers/reset/reset-dra7.c | 2 | ||||
| -rw-r--r-- | drivers/reset/reset-mediatek.c | 2 | ||||
| -rw-r--r-- | drivers/reset/reset-meson.c | 2 | ||||
| -rw-r--r-- | drivers/reset/reset-npcm.c | 2 | ||||
| -rw-r--r-- | drivers/reset/reset-raspberrypi.c | 2 | ||||
| -rw-r--r-- | drivers/reset/reset-sunxi.c | 2 | ||||
| -rw-r--r-- | drivers/reset/reset-uclass.c | 34 | ||||
| -rw-r--r-- | drivers/reset/reset-zynqmp.c | 11 | ||||
| -rw-r--r-- | drivers/reset/sandbox-reset-test.c | 14 | ||||
| -rw-r--r-- | drivers/reset/sandbox-reset.c | 60 | ||||
| -rw-r--r-- | drivers/reset/sti-reset.c | 2 | ||||
| -rw-r--r-- | drivers/reset/tegra-car-reset.c | 2 | ||||
| -rw-r--r-- | drivers/reset/tegra186-reset.c | 2 |
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, }; |
