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 <duwe@suse.de>
Co-authored-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Tested-by: Pedro Falcato <pfalcato@suse.de>
This commit is contained in:
Torsten Duwe
2026-06-04 10:50:04 +01:00
committed by Peter Robinson
co-authored by Oleksii Moisieiev
parent d0b2a1cb3f
commit 64ae1351b5
4 changed files with 107 additions and 0 deletions
+1
View File
@@ -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
+8
View File
@@ -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
+1
View File
@@ -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
+97
View File
@@ -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 <f.fainelli@gmail.com>
* 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),
};