diff options
| author | Torsten Duwe <[email protected]> | 2026-06-01 12:39:27 +0200 |
|---|---|---|
| committer | Peter Robinson <[email protected]> | 2026-06-04 10:50:04 +0100 |
| commit | 64ae1351b5203581a512ad8510e45870fdef4409 (patch) | |
| tree | fbc9782ee93a850b1fd8860161bf3476dfe8878f | |
| parent | d0b2a1cb3f33b63c316ad30aa9fda8ff02a6b01b (diff) | |
reset: Add RPi5 brcmstb reset facilities
A driver for Broadcom reset controllers ported from
linux/drivers/reset/reset-brcmstb.c to U-Boot.
Signed-off-by: Torsten Duwe <[email protected]>
Co-authored-by: Oleksii Moisieiev <[email protected]>
Tested-by: Pedro Falcato <[email protected]>
| -rw-r--r-- | configs/rpi_arm64_defconfig | 1 | ||||
| -rw-r--r-- | drivers/reset/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/reset/Makefile | 1 | ||||
| -rw-r--r-- | drivers/reset/reset-brcmstb.c | 97 |
4 files changed, 107 insertions, 0 deletions
diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig index 69e8e72c5d7..153d7ed301e 100644 --- a/configs/rpi_arm64_defconfig +++ b/configs/rpi_arm64_defconfig @@ -44,6 +44,7 @@ CONFIG_BCMGENET=y CONFIG_PCI_BRCMSTB=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set +CONFIG_RESET_BRCMSTB=y CONFIG_DM_RNG=y CONFIG_RNG_IPROC200=y # CONFIG_REQUIRE_SERIAL_CONSOLE is not set diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index ebf484d9df4..7f1b2a304e3 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -64,6 +64,14 @@ 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_UNIPHIER bool "Reset controller driver for UniPhier SoCs" depends on ARCH_UNIPHIER diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 088545c6473..ad5fe6b6184 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -13,6 +13,7 @@ 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_UNIPHIER) += reset-uniphier.o obj-$(CONFIG_RESET_AST2500) += reset-ast2500.o obj-$(CONFIG_RESET_AST2600) += reset-ast2600.o 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), +}; |
