diff options
Diffstat (limited to 'drivers/reset')
26 files changed, 752 insertions, 578 deletions
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 66911199c8b..db764ed5ace 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -64,6 +64,22 @@ 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_BRCMSTB_RESCAL + depends on ARCH_BCM283X + bool "Generic Rescal Reset controller driver for Broadcom" + help + Support rescal reset controller on Broadcom. + 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 @@ -91,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 @@ -100,6 +125,15 @@ config RESET_ROCKCHIP though is that some reset signals, like I2C or MISC reset multiple devices. +config SPL_RESET_ROCKCHIP + bool "SPL reset controller driver for Rockchip SoCs" + depends on SPL_DM_RESET && ARCH_ROCKCHIP && SPL_CLK + default y + help + Support for the reset controller on Rockchip SoCs in SPL. Select this + if you observe any reset-related warnings or errors when booting SPL, + such as when using UFS storage + config RESET_HSDK bool "Synopsys HSDK Reset Driver" depends on DM_RESET && TARGET_HSDK @@ -239,19 +273,11 @@ config RESET_AT91 config RESET_RZG2L_USBPHY_CTRL bool "Enable support for Renesas RZ/G2L USB 2.0 PHY control" - depends on DM_RESET - select REGULATOR_RZG2L_USBPHY + depends on DM_RESET && REGULATOR_RZG2L_USBPHY help Enable support for controlling USB 2.0 PHY resets on the Renesas RZ/G2L SoC. This is required for USB 2.0 functionality to work on this SoC. -config RESET_SPACEMIT_K1 - bool "Support for SPACEMIT's K1 Reset driver" - depends on DM_RESET - help - Support for SPACEMIT's K1 Reset system. Basic Assert/Deassert - is supported. - source "drivers/reset/stm32/Kconfig" endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 088545c6473..384f4336331 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -13,10 +13,13 @@ 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_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_ROCKCHIP) += reset-rockchip.o rst-rk3506.o rst-rk3528.o rst-rk3576.o rst-rk3588.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 obj-$(CONFIG_RESET_MEDIATEK) += reset-mediatek.o @@ -34,7 +37,7 @@ obj-$(CONFIG_RESET_DRA7) += reset-dra7.o obj-$(CONFIG_RESET_AT91) += reset-at91.o obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o -obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o +obj-$(CONFIG_CLK_SPACEMIT_K1) += spacemit/ obj-$(CONFIG_ARCH_STM32) += stm32/ obj-$(CONFIG_ARCH_STM32MP) += stm32/ 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-brcmstb-rescal.c b/drivers/reset/reset-brcmstb-rescal.c new file mode 100644 index 00000000000..fc8fcfa8b3f --- /dev/null +++ b/drivers/reset/reset-brcmstb-rescal.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Broadcom STB generic reset controller + * + * Copyright (C) 2024 EPAM Systems + * Moved from linux kernel: + * Copyright (C) 2018-2020 Broadcom + */ + +#include <asm/io.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <errno.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/iopoll.h> +#include <log.h> +#include <malloc.h> +#include <reset-uclass.h> + +#define BRCM_RESCAL_START 0x0 +#define BRCM_RESCAL_START_BIT BIT(0) +#define BRCM_RESCAL_CTRL 0x4 +#define BRCM_RESCAL_STATUS 0x8 +#define BRCM_RESCAL_STATUS_BIT BIT(0) + +struct brcm_rescal_reset { + void __iomem *base; +}; + +/* Also doubles a deassert */ +static int brcm_rescal_reset_set(struct reset_ctl *rst) +{ + struct brcm_rescal_reset *data = dev_get_priv(rst->dev); + void __iomem *base = data->base; + u32 reg; + int ret; + + reg = readl(base + BRCM_RESCAL_START); + writel(reg | BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START); + reg = readl(base + BRCM_RESCAL_START); + if (!(reg & BRCM_RESCAL_START_BIT)) { + dev_err(rst->dev, "failed to start SATA/PCIe rescal\n"); + return -EIO; + } + + ret = readl_poll_timeout(base + BRCM_RESCAL_STATUS, reg, + (reg & BRCM_RESCAL_STATUS_BIT), 100); + if (ret) { + dev_err(rst->dev, "time out on SATA/PCIe rescal\n"); + return ret; + } + + reg = readl(base + BRCM_RESCAL_START); + writel(reg & ~BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START); + + dev_dbg(rst->dev, "SATA/PCIe rescal success\n"); + return 0; +} + +/* A dummy function - deassert/reset does all the work */ +static int brcm_rescal_reset_assert(struct reset_ctl *rst) +{ + return 0; +} + +static int brcm_rescal_reset_xlate(struct reset_ctl *reset_ctl, + struct ofnode_phandle_args *args) +{ + /* This is needed if #reset-cells == 0. */ + return 0; +} + +static const struct reset_ops brcm_rescal_reset_ops = { + .rst_deassert = brcm_rescal_reset_set, + .rst_assert = brcm_rescal_reset_assert, + .of_xlate = brcm_rescal_reset_xlate, +}; + +static int brcm_rescal_reset_probe(struct udevice *dev) +{ + struct brcm_rescal_reset *data = dev_get_priv(dev); + + data->base = dev_remap_addr(dev); + if (!data->base) + return -EINVAL; + + return 0; +} + +static const struct udevice_id brcm_rescal_reset_of_match[] = { + {.compatible = "brcm,bcm7216-pcie-sata-rescal"}, + {}, +}; + +U_BOOT_DRIVER(brcmstb_reset_rescal) = { + .name = "brcmstb-reset-rescal", + .id = UCLASS_RESET, + .of_match = brcm_rescal_reset_of_match, + .ops = &brcm_rescal_reset_ops, + .probe = brcm_rescal_reset_probe, + .priv_auto = sizeof(struct brcm_rescal_reset), +}; 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), +}; 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-spacemit-k1.c b/drivers/reset/reset-spacemit-k1.c deleted file mode 100644 index 613e002fc4f..00000000000 --- a/drivers/reset/reset-spacemit-k1.c +++ /dev/null @@ -1,548 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2022 Spacemit Inc. - * Copyright (C) 2025 Huan Zhou <[email protected]> - */ - -#include <asm/io.h> -#include <config.h> -#include <dm.h> -#include <dm/device_compat.h> -#include <dm/device-internal.h> -#include <dm/lists.h> -#include <dt-bindings/reset/spacemit-k1-reset.h> -#include <linux/bitops.h> -#include <reset-uclass.h> - -/* APBC register offset */ -#define APBC_UART1_CLK_RST 0x0 -#define APBC_UART2_CLK_RST 0x4 -#define APBC_GPIO_CLK_RST 0x8 -#define APBC_PWM0_CLK_RST 0xc -#define APBC_PWM1_CLK_RST 0x10 -#define APBC_PWM2_CLK_RST 0x14 -#define APBC_PWM3_CLK_RST 0x18 -#define APBC_TWSI8_CLK_RST 0x20 -#define APBC_UART3_CLK_RST 0x24 -#define APBC_RTC_CLK_RST 0x28 -#define APBC_TWSI0_CLK_RST 0x2c -#define APBC_TWSI1_CLK_RST 0x30 -#define APBC_TIMERS1_CLK_RST 0x34 -#define APBC_TWSI2_CLK_RST 0x38 -#define APBC_AIB_CLK_RST 0x3c -#define APBC_TWSI4_CLK_RST 0x40 -#define APBC_TIMERS2_CLK_RST 0x44 -#define APBC_ONEWIRE_CLK_RST 0x48 -#define APBC_TWSI5_CLK_RST 0x4c -#define APBC_DRO_CLK_RST 0x58 -#define APBC_IR_CLK_RST 0x5c -#define APBC_TWSI6_CLK_RST 0x60 -#define APBC_TWSI7_CLK_RST 0x68 -#define APBC_TSEN_CLK_RST 0x6c - -#define APBC_UART4_CLK_RST 0x70 -#define APBC_UART5_CLK_RST 0x74 -#define APBC_UART6_CLK_RST 0x78 -#define APBC_SSP3_CLK_RST 0x7c - -#define APBC_SSPA0_CLK_RST 0x80 -#define APBC_SSPA1_CLK_RST 0x84 - -#define APBC_IPC_AP2AUD_CLK_RST 0x90 -#define APBC_UART7_CLK_RST 0x94 -#define APBC_UART8_CLK_RST 0x98 -#define APBC_UART9_CLK_RST 0x9c - -#define APBC_CAN0_CLK_RST 0xa0 -#define APBC_PWM4_CLK_RST 0xa8 -#define APBC_PWM5_CLK_RST 0xac -#define APBC_PWM6_CLK_RST 0xb0 -#define APBC_PWM7_CLK_RST 0xb4 -#define APBC_PWM8_CLK_RST 0xb8 -#define APBC_PWM9_CLK_RST 0xbc -#define APBC_PWM10_CLK_RST 0xc0 -#define APBC_PWM11_CLK_RST 0xc4 -#define APBC_PWM12_CLK_RST 0xc8 -#define APBC_PWM13_CLK_RST 0xcc -#define APBC_PWM14_CLK_RST 0xd0 -#define APBC_PWM15_CLK_RST 0xd4 -#define APBC_PWM16_CLK_RST 0xd8 -#define APBC_PWM17_CLK_RST 0xdc -#define APBC_PWM18_CLK_RST 0xe0 -#define APBC_PWM19_CLK_RST 0xe4 -/* end of APBC register offset */ - -/* MPMU register offset */ -#define MPMU_WDTPCR 0x200 -/* end of MPMU register offset */ - -/* APMU register offset */ -#define APMU_JPG_CLK_RES_CTRL 0x20 -#define APMU_CSI_CCIC2_CLK_RES_CTRL 0x24 -#define APMU_ISP_CLK_RES_CTRL 0x38 -#define APMU_LCD_CLK_RES_CTRL1 0x44 -#define APMU_LCD_SPI_CLK_RES_CTRL 0x48 -#define APMU_LCD_CLK_RES_CTRL2 0x4c -#define APMU_CCIC_CLK_RES_CTRL 0x50 -#define APMU_SDH0_CLK_RES_CTRL 0x54 -#define APMU_SDH1_CLK_RES_CTRL 0x58 -#define APMU_USB_CLK_RES_CTRL 0x5c -#define APMU_QSPI_CLK_RES_CTRL 0x60 -#define APMU_USB_CLK_RES_CTRL 0x5c -#define APMU_DMA_CLK_RES_CTRL 0x64 -#define APMU_AES_CLK_RES_CTRL 0x68 -#define APMU_VPU_CLK_RES_CTRL 0xa4 -#define APMU_GPU_CLK_RES_CTRL 0xcc -#define APMU_SDH2_CLK_RES_CTRL 0xe0 -#define APMU_PMUA_MC_CTRL 0xe8 -#define APMU_PMU_CC2_AP 0x100 -#define APMU_PMUA_EM_CLK_RES_CTRL 0x104 - -#define APMU_AUDIO_CLK_RES_CTRL 0x14c -#define APMU_HDMI_CLK_RES_CTRL 0x1B8 - -#define APMU_PCIE_CLK_RES_CTRL_0 0x3cc -#define APMU_PCIE_CLK_RES_CTRL_1 0x3d4 -#define APMU_PCIE_CLK_RES_CTRL_2 0x3dc - -#define APMU_EMAC0_CLK_RES_CTRL 0x3e4 -#define APMU_EMAC1_CLK_RES_CTRL 0x3ec -/* end of APMU register offset */ - -/* APBC2 register offset */ -#define APBC2_UART1_CLK_RST 0x00 -#define APBC2_SSP2_CLK_RST 0x04 -#define APBC2_TWSI3_CLK_RST 0x08 -#define APBC2_RTC_CLK_RST 0x0c -#define APBC2_TIMERS0_CLK_RST 0x10 -#define APBC2_KPC_CLK_RST 0x14 -#define APBC2_GPIO_CLK_RST 0x1c -/* end of APBC2 register offset */ - -enum spacemit_reset_base_type { - RST_BASE_TYPE_MPMU = 0, - RST_BASE_TYPE_APMU = 1, - RST_BASE_TYPE_APBC = 2, - RST_BASE_TYPE_APBS = 3, - RST_BASE_TYPE_CIU = 4, - RST_BASE_TYPE_DCIU = 5, - RST_BASE_TYPE_DDRC = 6, - RST_BASE_TYPE_AUDC = 7, - RST_BASE_TYPE_APBC2 = 8, -}; - -struct spacemit_reset_signal { - u32 offset; - u32 mask; - u32 deassert_val; - u32 assert_val; - enum spacemit_reset_base_type type; -}; - -struct spacemit_reset_base { - void __iomem *mpmu_base; - void __iomem *apmu_base; - void __iomem *apbc_base; - void __iomem *apbs_base; - void __iomem *ciu_base; - void __iomem *dciu_base; - void __iomem *ddrc_base; - void __iomem *audio_ctrl_base; - void __iomem *apbc2_base; -}; - -struct spacemit_reset { - struct spacemit_reset_base io_base; - const struct spacemit_reset_signal *signals; -}; - -enum { - RESET_TWSI6_SPL = 0, - RESET_TWSI8_SPL, - RESET_SDH_AXI_SPL, - RESET_SDH0_SPL, - RESET_USB_AXI_SPL, - RESET_USBP1_AXI_SPL, - RESET_USB3_0_SPL, - RESET_QSPI_SPL, - RESET_QSPI_BUS_SPL, - RESET_AES_SPL, - RESET_SDH2_SPL, - RESET_NUMBER_SPL -}; - -static const struct spacemit_reset_signal - k1_reset_signals[RESET_NUMBER] = { - [RESET_UART1] = { APBC_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART2] = { APBC_UART2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_GPIO] = { APBC_GPIO_CLK_RST, BIT(2), 0, - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM0] = { APBC_PWM0_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM1] = { APBC_PWM1_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM2] = { APBC_PWM2_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM3] = { APBC_PWM3_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM4] = { APBC_PWM4_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM5] = { APBC_PWM5_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM6] = { APBC_PWM6_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM7] = { APBC_PWM7_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM8] = { APBC_PWM8_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM9] = { APBC_PWM9_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM10] = { APBC_PWM10_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM11] = { APBC_PWM11_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM12] = { APBC_PWM12_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM13] = { APBC_PWM13_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM14] = { APBC_PWM14_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM15] = { APBC_PWM15_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM16] = { APBC_PWM16_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM17] = { APBC_PWM17_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM18] = { APBC_PWM18_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_PWM19] = { APBC_PWM19_CLK_RST, - BIT(2) | BIT(0), - BIT(0), - BIT(2), - RST_BASE_TYPE_APBC }, - [RESET_SSP3] = { APBC_SSP3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART3] = { APBC_UART3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_RTC] = { APBC_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI0] = { APBC_TWSI0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TIMERS1] = { APBC_TIMERS1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_AIB] = { APBC_AIB_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TIMERS2] = { APBC_TIMERS2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_ONEWIRE] = { APBC_ONEWIRE_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_SSPA0] = { APBC_SSPA0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_SSPA1] = { APBC_SSPA1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_DRO] = { APBC_DRO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_IR] = { APBC_IR_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI1] = { APBC_TWSI1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TSEN] = { APBC_TSEN_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI2] = { APBC_TWSI2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI4] = { APBC_TWSI4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI5] = { APBC_TWSI5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI6] = { APBC_TWSI6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI7] = { APBC_TWSI7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_TWSI8] = { APBC_TWSI8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_IPC_AP2AUD] = { APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART4] = { APBC_UART4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART5] = { APBC_UART5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART6] = { APBC_UART6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART7] = { APBC_UART7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART8] = { APBC_UART8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_UART9] = { APBC_UART9_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - [RESET_CAN0] = { APBC_CAN0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC }, - /* MPMU */ - [RESET_WDT] = { MPMU_WDTPCR, BIT(2), 0, BIT(2), RST_BASE_TYPE_MPMU }, - /* APMU */ - [RESET_JPG] = { APMU_JPG_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_CSI] = { APMU_CSI_CCIC2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_CCIC2_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL, - BIT(2), - BIT(2), - 0, - RST_BASE_TYPE_APMU }, - [RESET_CCIC3_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL, - BIT(29), - BIT(29), - 0, - RST_BASE_TYPE_APMU }, - [RESET_ISP] = { APMU_ISP_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_ISP_AHB] = { APMU_ISP_CLK_RES_CTRL, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU }, - [RESET_ISP_CI] = { APMU_ISP_CLK_RES_CTRL, BIT(16), BIT(16), 0, RST_BASE_TYPE_APMU }, - [RESET_ISP_CPP] = { APMU_ISP_CLK_RES_CTRL, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU }, - [RESET_LCD] = { APMU_LCD_CLK_RES_CTRL1, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU }, - [RESET_DSI_ESC] = { APMU_LCD_CLK_RES_CTRL1, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU }, - [RESET_V2D] = { APMU_LCD_CLK_RES_CTRL1, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU }, - [RESET_MIPI] = { APMU_LCD_CLK_RES_CTRL1, BIT(15), BIT(15), 0, RST_BASE_TYPE_APMU }, - [RESET_LCD_SPI] = { APMU_LCD_SPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_LCD_SPI_BUS] = { APMU_LCD_SPI_CLK_RES_CTRL, - BIT(4), - BIT(4), - 0, - RST_BASE_TYPE_APMU }, - [RESET_LCD_SPI_HBUS] = { APMU_LCD_SPI_CLK_RES_CTRL, - BIT(2), - BIT(2), - 0, - RST_BASE_TYPE_APMU }, - [RESET_LCD_MCLK] = { APMU_LCD_CLK_RES_CTRL2, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU }, - [RESET_CCIC_4X] = { APMU_CCIC_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_CCIC1_PHY] = { APMU_CCIC_CLK_RES_CTRL, BIT(2), BIT(2), 0, RST_BASE_TYPE_APMU }, - [RESET_SDH_AXI] = { APMU_SDH0_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_SDH0] = { APMU_SDH0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_SDH1] = { APMU_SDH1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_USB_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_USBP1_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU }, - [RESET_USB3_0] = { APMU_USB_CLK_RES_CTRL, - BIT(9) | BIT(10) | BIT(11), - BIT(9) | BIT(10) | BIT(11), - 0, - RST_BASE_TYPE_APMU }, - [RESET_QSPI] = { APMU_QSPI_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_QSPI_BUS] = { APMU_QSPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_DMA] = { APMU_DMA_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_AES] = { APMU_AES_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU }, - [RESET_VPU] = { APMU_VPU_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_GPU] = { APMU_GPU_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_SDH2] = { APMU_SDH2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_MC] = { APMU_PMUA_MC_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_EM_AXI] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU }, - [RESET_EM] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_AUDIO_SYS] = { APMU_AUDIO_CLK_RES_CTRL, - BIT(0) | BIT(2) | BIT(3), - BIT(0) | BIT(2) | BIT(3), - 0, - RST_BASE_TYPE_APMU }, - [RESET_HDMI] = { APMU_HDMI_CLK_RES_CTRL, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU }, - [RESET_PCIE0] = { APMU_PCIE_CLK_RES_CTRL_0, - BIT(3) | BIT(4) | BIT(5) | BIT(8), - BIT(3) | BIT(4) | BIT(5), - BIT(8), - RST_BASE_TYPE_APMU }, - [RESET_PCIE1] = { APMU_PCIE_CLK_RES_CTRL_1, - BIT(3) | BIT(4) | BIT(5) | BIT(8), - BIT(3) | BIT(4) | BIT(5), - BIT(8), - RST_BASE_TYPE_APMU }, - [RESET_PCIE2] = { APMU_PCIE_CLK_RES_CTRL_2, 0x138, 0x38, 0x100, RST_BASE_TYPE_APMU }, - [RESET_EMAC0] = { APMU_EMAC0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_EMAC1] = { APMU_EMAC1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU }, - [RESET_SEC_UART1] = { APBC2_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_SSP2] = { APBC2_SSP2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_TWSI3] = { APBC2_TWSI3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_RTC] = { APBC2_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_TIMERS0] = { APBC2_TIMERS0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_KPC] = { APBC2_KPC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - [RESET_SEC_GPIO] = { APBC2_GPIO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 }, - }; - -static u32 spacemit_reset_read(struct spacemit_reset *reset, u32 id) -{ - void __iomem *base; - - switch (reset->signals[id].type) { - case RST_BASE_TYPE_APMU: - base = reset->io_base.apmu_base; - break; - case RST_BASE_TYPE_APBC: - base = reset->io_base.apbc_base; - break; - default: - base = reset->io_base.apbc_base; - break; - } - - return readl(base + reset->signals[id].offset); -} - -static void spacemit_reset_write(struct spacemit_reset *reset, u32 value, u32 id) -{ - void __iomem *base; - - switch (reset->signals[id].type) { - case RST_BASE_TYPE_APMU: - base = reset->io_base.apmu_base; - break; - case RST_BASE_TYPE_APBC: - base = reset->io_base.apbc_base; - break; - default: - base = reset->io_base.apbc_base; - break; - } - - writel(value, base + reset->signals[id].offset); -} - -static void spacemit_reset_set(struct reset_ctl *rst, u32 id, bool assert) -{ - u32 value; - struct spacemit_reset *reset = dev_get_priv(rst->dev); - - value = spacemit_reset_read(reset, id); - - if (assert) { - value &= ~reset->signals[id].mask; - value |= reset->signals[id].assert_val; - } else { - value &= ~reset->signals[id].mask; - value |= reset->signals[id].deassert_val; - } - - spacemit_reset_write(reset, value, id); -} - -static int spacemit_reset_update(struct reset_ctl *rst, bool assert) -{ - if (rst->id < RESET_UART1 || rst->id >= RESET_NUMBER) - return 0; - - /* can not write to twsi8 */ - if (rst->id == RESET_TWSI8) - return 0; - - spacemit_reset_set(rst, rst->id, assert); - return 0; -} - -static int spacemit_reset_assert(struct reset_ctl *rst) -{ - return spacemit_reset_update(rst, true); -} - -static int spacemit_reset_deassert(struct reset_ctl *rst) -{ - return spacemit_reset_update(rst, false); -} - -static int spacemit_k1_reset_probe(struct udevice *dev) -{ - struct spacemit_reset *reset = dev_get_priv(dev); - - reset->io_base.mpmu_base = (void *)dev_remap_addr_index(dev, 0); - if (!reset->io_base.mpmu_base) { - pr_err("failed to map mpmu registers\n"); - goto out; - } - - reset->io_base.apmu_base = (void *)dev_remap_addr_index(dev, 1); - if (!reset->io_base.apmu_base) { - pr_err("failed to map apmu registers\n"); - goto out; - } - - reset->io_base.apbc_base = (void *)dev_remap_addr_index(dev, 2); - if (!reset->io_base.apbc_base) { - pr_err("failed to map apbc registers\n"); - goto out; - } - - reset->io_base.apbs_base = (void *)dev_remap_addr_index(dev, 3); - if (!reset->io_base.apbs_base) { - pr_err("failed to map apbs registers\n"); - goto out; - } - - reset->io_base.ciu_base = (void *)dev_remap_addr_index(dev, 4); - if (!reset->io_base.ciu_base) { - pr_err("failed to map ciu registers\n"); - goto out; - } - - reset->io_base.dciu_base = (void *)dev_remap_addr_index(dev, 5); - if (!reset->io_base.dciu_base) { - pr_err("failed to map dragon ciu registers\n"); - goto out; - } - - reset->io_base.ddrc_base = (void *)dev_remap_addr_index(dev, 6); - if (!reset->io_base.ddrc_base) { - pr_err("failed to map ddrc registers\n"); - goto out; - } - - reset->io_base.apbc2_base = (void *)dev_remap_addr_index(dev, 7); - if (!reset->io_base.apbc2_base) { - pr_err("failed to map apbc2 registers\n"); - goto out; - } - - reset->signals = k1_reset_signals; - -out: - return 0; -} - -const struct reset_ops k1_reset_ops = { - .rst_assert = spacemit_reset_assert, - .rst_deassert = spacemit_reset_deassert, -}; - -static const struct udevice_id k1_reset_ids[] = { - { .compatible = "spacemit,k1-reset", }, - {}, -}; - -U_BOOT_DRIVER(k1_reset) = { - .name = "spacemit,k1-reset", - .id = UCLASS_RESET, - .ops = &k1_reset_ops, - .of_match = k1_reset_ids, - .probe = spacemit_k1_reset_probe, - .priv_auto = sizeof(struct spacemit_reset), -}; 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/spacemit/Makefile b/drivers/reset/spacemit/Makefile new file mode 100644 index 00000000000..16722c68954 --- /dev/null +++ b/drivers/reset/spacemit/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# SpacemiT reset drivers + +obj-y += reset-spacemit-k1.o diff --git a/drivers/reset/spacemit/reset-spacemit-k1.c b/drivers/reset/spacemit/reset-spacemit-k1.c new file mode 100644 index 00000000000..129e1cc96f1 --- /dev/null +++ b/drivers/reset/spacemit/reset-spacemit-k1.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * SpacemiT K1 reset driver (syscon-bound). + * + * Copyright (C) 2022 Spacemit Inc. + * Copyright (C) 2025 Huan Zhou <[email protected]> + * Copyright (C) 2026 RISCstar Ltd. + */ + +#include <asm/io.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dt-bindings/clock/spacemit,k1-syscon.h> +#include <linux/bitops.h> +#include <malloc.h> +#include <reset-uclass.h> +#include <soc/spacemit/k1-reset.h> +#include <soc/spacemit/k1-syscon.h> + +/* =================================================================== + * Per-syscon reset signal tables. + * + * Indexed by the kernel-side per-syscon-local IDs from + * <dt-bindings/clock/spacemit,k1-syscon.h>. Each entry is + * (offset, assert_mask, deassert_mask): bits in assert_mask are set + * when the reset line is asserted; bits in deassert_mask are set when + * deasserted; the union (assert_mask | deassert_mask) is the set of + * bits the controller will overwrite on each transition. + * + * Layout mirrors the kernel-side K1 reset driver. + * =================================================================== + */ + +struct spacemit_k1_reset_data { + u32 offset; + u32 assert_mask; + u32 deassert_mask; +}; + +#define RESET_DATA(o, a, d) { \ + .offset = (o), .assert_mask = (a), .deassert_mask = (d) \ +} + +static const struct spacemit_k1_reset_data k1_mpmu_resets[] = { + [RESET_WDT] = RESET_DATA(MPMU_WDTPCR, BIT(2), 0), +}; + +static const struct spacemit_k1_reset_data k1_apbc_resets[] = { + [RESET_UART0] = RESET_DATA(APBC_UART1_CLK_RST, BIT(2), 0), + [RESET_UART2] = RESET_DATA(APBC_UART2_CLK_RST, BIT(2), 0), + [RESET_UART3] = RESET_DATA(APBC_UART3_CLK_RST, BIT(2), 0), + [RESET_UART4] = RESET_DATA(APBC_UART4_CLK_RST, BIT(2), 0), + [RESET_UART5] = RESET_DATA(APBC_UART5_CLK_RST, BIT(2), 0), + [RESET_UART6] = RESET_DATA(APBC_UART6_CLK_RST, BIT(2), 0), + [RESET_UART7] = RESET_DATA(APBC_UART7_CLK_RST, BIT(2), 0), + [RESET_UART8] = RESET_DATA(APBC_UART8_CLK_RST, BIT(2), 0), + [RESET_UART9] = RESET_DATA(APBC_UART9_CLK_RST, BIT(2), 0), + [RESET_GPIO] = RESET_DATA(APBC_GPIO_CLK_RST, BIT(2), 0), + [RESET_PWM0] = RESET_DATA(APBC_PWM0_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM1] = RESET_DATA(APBC_PWM1_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM2] = RESET_DATA(APBC_PWM2_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM3] = RESET_DATA(APBC_PWM3_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM4] = RESET_DATA(APBC_PWM4_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM5] = RESET_DATA(APBC_PWM5_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM6] = RESET_DATA(APBC_PWM6_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM7] = RESET_DATA(APBC_PWM7_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM8] = RESET_DATA(APBC_PWM8_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM9] = RESET_DATA(APBC_PWM9_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM10] = RESET_DATA(APBC_PWM10_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM11] = RESET_DATA(APBC_PWM11_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM12] = RESET_DATA(APBC_PWM12_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM13] = RESET_DATA(APBC_PWM13_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM14] = RESET_DATA(APBC_PWM14_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM15] = RESET_DATA(APBC_PWM15_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM16] = RESET_DATA(APBC_PWM16_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM17] = RESET_DATA(APBC_PWM17_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM18] = RESET_DATA(APBC_PWM18_CLK_RST, BIT(2), BIT(0)), + [RESET_PWM19] = RESET_DATA(APBC_PWM19_CLK_RST, BIT(2), BIT(0)), + [RESET_SSP3] = RESET_DATA(APBC_SSP3_CLK_RST, BIT(2), 0), + [RESET_RTC] = RESET_DATA(APBC_RTC_CLK_RST, BIT(2), 0), + [RESET_TWSI0] = RESET_DATA(APBC_TWSI0_CLK_RST, BIT(2), 0), + [RESET_TWSI1] = RESET_DATA(APBC_TWSI1_CLK_RST, BIT(2), 0), + [RESET_TWSI2] = RESET_DATA(APBC_TWSI2_CLK_RST, BIT(2), 0), + [RESET_TWSI4] = RESET_DATA(APBC_TWSI4_CLK_RST, BIT(2), 0), + [RESET_TWSI5] = RESET_DATA(APBC_TWSI5_CLK_RST, BIT(2), 0), + [RESET_TWSI6] = RESET_DATA(APBC_TWSI6_CLK_RST, BIT(2), 0), + [RESET_TWSI7] = RESET_DATA(APBC_TWSI7_CLK_RST, BIT(2), 0), + [RESET_TWSI8] = RESET_DATA(APBC_TWSI8_CLK_RST, BIT(2), 0), + [RESET_TIMERS1] = RESET_DATA(APBC_TIMERS1_CLK_RST, BIT(2), 0), + [RESET_TIMERS2] = RESET_DATA(APBC_TIMERS2_CLK_RST, BIT(2), 0), + [RESET_AIB] = RESET_DATA(APBC_AIB_CLK_RST, BIT(2), 0), + [RESET_ONEWIRE] = RESET_DATA(APBC_ONEWIRE_CLK_RST, BIT(2), 0), + [RESET_SSPA0] = RESET_DATA(APBC_SSPA0_CLK_RST, BIT(2), 0), + [RESET_SSPA1] = RESET_DATA(APBC_SSPA1_CLK_RST, BIT(2), 0), + [RESET_DRO] = RESET_DATA(APBC_DRO_CLK_RST, BIT(2), 0), + [RESET_IR] = RESET_DATA(APBC_IR_CLK_RST, BIT(2), 0), + [RESET_TSEN] = RESET_DATA(APBC_TSEN_CLK_RST, BIT(2), 0), + [RESET_IPC_AP2AUD] = RESET_DATA(APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0), + [RESET_CAN0] = RESET_DATA(APBC_CAN0_CLK_RST, BIT(2), 0), +}; + +static const struct spacemit_k1_reset_data k1_apmu_resets[] = { + [RESET_CCIC_4X] = RESET_DATA(APMU_CCIC_CLK_RES_CTRL, 0, BIT(1)), + [RESET_CCIC1_PHY] = RESET_DATA(APMU_CCIC_CLK_RES_CTRL, 0, BIT(2)), + [RESET_SDH_AXI] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(0)), + [RESET_SDH0] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(1)), + [RESET_SDH1] = RESET_DATA(APMU_SDH1_CLK_RES_CTRL, 0, BIT(1)), + [RESET_SDH2] = RESET_DATA(APMU_SDH2_CLK_RES_CTRL, 0, BIT(1)), + [RESET_USBP1_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(4)), + [RESET_USB_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(0)), + [RESET_USB30_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(9)), + [RESET_USB30_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(10)), + [RESET_USB30_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(11)), + [RESET_QSPI] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(1)), + [RESET_QSPI_BUS] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(0)), + [RESET_DMA] = RESET_DATA(APMU_DMA_CLK_RES_CTRL, 0, BIT(0)), + [RESET_AES] = RESET_DATA(APMU_AES_CLK_RES_CTRL, 0, BIT(4)), + [RESET_VPU] = RESET_DATA(APMU_VPU_CLK_RES_CTRL, 0, BIT(0)), + [RESET_GPU] = RESET_DATA(APMU_GPU_CLK_RES_CTRL, 0, BIT(1)), + [RESET_EMMC] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(1)), + [RESET_EMMC_X] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(0)), + [RESET_AUDIO_SYS] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(0)), + [RESET_AUDIO_MCU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(2)), + [RESET_AUDIO_APMU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(3)), + [RESET_HDMI] = RESET_DATA(APMU_HDMI_CLK_RES_CTRL, 0, BIT(9)), + [RESET_PCIE0_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(3)), + [RESET_PCIE0_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(4)), + [RESET_PCIE0_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(5)), + [RESET_PCIE0_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, BIT(8), 0), + [RESET_PCIE1_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(3)), + [RESET_PCIE1_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(4)), + [RESET_PCIE1_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(5)), + [RESET_PCIE1_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, BIT(8), 0), + [RESET_PCIE2_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(3)), + [RESET_PCIE2_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(4)), + [RESET_PCIE2_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(5)), + [RESET_PCIE2_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, BIT(8), 0), + [RESET_EMAC0] = RESET_DATA(APMU_EMAC0_CLK_RES_CTRL, 0, BIT(1)), + [RESET_EMAC1] = RESET_DATA(APMU_EMAC1_CLK_RES_CTRL, 0, BIT(1)), + [RESET_JPG] = RESET_DATA(APMU_JPG_CLK_RES_CTRL, 0, BIT(0)), + [RESET_CCIC2PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(2)), + [RESET_CCIC3PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(29)), + [RESET_CSI] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(1)), + [RESET_ISP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(0)), + [RESET_ISP_CPP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(27)), + [RESET_ISP_BUS] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(3)), + [RESET_ISP_CI] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(16)), + [RESET_DPU_MCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL2, 0, BIT(9)), + [RESET_DPU_ESC] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(3)), + [RESET_DPU_HCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(4)), + [RESET_DPU_SPIBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(4)), + [RESET_DPU_SPI_HBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(2)), + [RESET_V2D] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(27)), + [RESET_MIPI] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(15)), + [RESET_MC] = RESET_DATA(APMU_PMUA_MC_CTRL, 0, BIT(0)), +}; + +static const struct spacemit_k1_reset_data k1_apbc2_resets[] = { + [RESET_APBC2_UART1] = RESET_DATA(APBC2_UART1_CLK_RST, BIT(2), 0), + [RESET_APBC2_SSP2] = RESET_DATA(APBC2_SSP2_CLK_RST, BIT(2), 0), + [RESET_APBC2_TWSI3] = RESET_DATA(APBC2_TWSI3_CLK_RST, BIT(2), 0), + [RESET_APBC2_RTC] = RESET_DATA(APBC2_RTC_CLK_RST, BIT(2), 0), + [RESET_APBC2_TIMERS0] = RESET_DATA(APBC2_TIMERS0_CLK_RST, BIT(2), 0), + [RESET_APBC2_KPC] = RESET_DATA(APBC2_KPC_CLK_RST, BIT(2), 0), + [RESET_APBC2_GPIO] = RESET_DATA(APBC2_GPIO_CLK_RST, BIT(2), 0), +}; + +/* =================================================================== + * Driver + * =================================================================== + */ + +struct spacemit_k1_reset_priv { + void __iomem *base; + const struct spacemit_k1_reset_data *table; + size_t table_size; +}; + +static int spacemit_k1_reset_xfer(struct reset_ctl *rst, bool assert) +{ + struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev); + const struct spacemit_k1_reset_data *e; + u32 v; + + if (rst->id >= priv->table_size) + return -EINVAL; + + e = &priv->table[rst->id]; + if (e->assert_mask == 0 && e->deassert_mask == 0) + return -EINVAL; /* not owned by this syscon */ + + v = readl(priv->base + e->offset); + v &= ~(e->assert_mask | e->deassert_mask); + v |= assert ? e->assert_mask : e->deassert_mask; + writel(v, priv->base + e->offset); + + return 0; +} + +static int spacemit_k1_reset_assert(struct reset_ctl *rst) +{ + return spacemit_k1_reset_xfer(rst, true); +} + +static int spacemit_k1_reset_deassert(struct reset_ctl *rst) +{ + return spacemit_k1_reset_xfer(rst, false); +} + +static int spacemit_k1_reset_request(struct reset_ctl *rst) +{ + struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev); + + return rst->id < priv->table_size ? 0 : -EINVAL; +} + +static const struct reset_ops spacemit_k1_reset_ops = { + .request = spacemit_k1_reset_request, + .rst_assert = spacemit_k1_reset_assert, + .rst_deassert = spacemit_k1_reset_deassert, +}; + +static int spacemit_k1_reset_probe(struct udevice *dev) +{ + struct spacemit_k1_reset_priv *priv = dev_get_priv(dev); + + priv->base = (void __iomem *)dev_remap_addr(dev); + if (!priv->base) + return -ENODEV; + + return 0; +} + +U_BOOT_DRIVER(spacemit_k1_reset) = { + .name = "spacemit_k1_reset", + .id = UCLASS_RESET, + .ops = &spacemit_k1_reset_ops, + .probe = spacemit_k1_reset_probe, + .priv_auto = sizeof(struct spacemit_k1_reset_priv), + .flags = DM_FLAG_PRE_RELOC, +}; + +int spacemit_k1_reset_bind(struct udevice *parent, + enum spacemit_k1_reset_syscon syscon) +{ + struct spacemit_k1_reset_priv *priv; + struct udevice *rst_dev; + const struct spacemit_k1_reset_data *table; + size_t table_size; + int ret; + + switch (syscon) { + case SPACEMIT_K1_RESET_MPMU: + table = k1_mpmu_resets; + table_size = ARRAY_SIZE(k1_mpmu_resets); + break; + case SPACEMIT_K1_RESET_APMU: + table = k1_apmu_resets; + table_size = ARRAY_SIZE(k1_apmu_resets); + break; + case SPACEMIT_K1_RESET_APBC: + table = k1_apbc_resets; + table_size = ARRAY_SIZE(k1_apbc_resets); + break; + case SPACEMIT_K1_RESET_APBC2: + table = k1_apbc2_resets; + table_size = ARRAY_SIZE(k1_apbc2_resets); + break; + default: + return -EINVAL; + } + + ret = device_bind_driver_to_node(parent, "spacemit_k1_reset", "reset", + dev_ofnode(parent), &rst_dev); + if (ret) + return ret; + + priv = malloc(sizeof(*priv)); + if (!priv) { + device_unbind(rst_dev); + return -ENOMEM; + } + priv->table = table; + priv->table_size = table_size; + dev_set_priv(rst_dev, priv); + + return 0; +} 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/stm32/stm32-reset-mp21.c b/drivers/reset/stm32/stm32-reset-mp21.c index 7d169d7582f..0e92b0f5d5d 100644 --- a/drivers/reset/stm32/stm32-reset-mp21.c +++ b/drivers/reset/stm32/stm32-reset-mp21.c @@ -5,7 +5,7 @@ */ #include <dm.h> -#include <stm32-reset-core.h> +#include "stm32-reset-core.h" #include <stm32mp21_rcc.h> #include <dt-bindings/reset/st,stm32mp21-rcc.h> 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, }; |
