> -----Original Message-----
> From: Yuslaimi, Alif Zakuan <alif.zakuan.yusla...@altera.com>
> Sent: Thursday, June 12, 2025 4:08 PM
> To: u-boot@lists.denx.de
> Cc: Tom Rini <tr...@konsulko.com>; Marek Vasut <ma...@denx.de>; Simon
> Goldschmidt <simon.k.r.goldschm...@gmail.com>; Chee, Tien Fong
> <tien.fong.c...@altera.com>; Meng, Tingting <tingting.m...@altera.com>;
> Lim, Jit Loon <jit.loon....@altera.com>; Yuslaimi, Alif Zakuan
> <alif.zakuan.yusla...@altera.com>
> Subject: [PATCH v1] arch: arm: agilex5: Enable power manager for Agilex5
>
> From: Alif Zakuan Yuslaimi <alif.zakuan.yusla...@altera.com>
>
> Agilex5 FSBL is required to disable the power of unused peripheral SRAM
> blocks to reduce power consumption.
>
> Introducing a new power manager driver for Agilex5 which will be called as
> part of Agilex5 SPL initialization process.
>
> This driver will read the peripheral handoff data obtained from the bitstream
> and will power off the specified peripheral's SRAM from the handoff data
> values.
>
> Signed-off-by: Alif Zakuan Yuslaimi <alif.zakuan.yusla...@altera.com>
> ---
> MAINTAINERS | 1 +
> arch/arm/dts/socfpga_agilex5-u-boot.dtsi | 6 +
> .../mach-socfpga/include/mach/handoff_soc64.h | 1 +
> arch/arm/mach-socfpga/spl_agilex5.c | 6 +
> configs/socfpga_agilex5_defconfig | 2 +
> .../power/altr,pmgr-agilex5.yaml | 39 ++++++
> drivers/power/domain/Kconfig | 8 ++
> drivers/power/domain/Makefile | 1 +
> drivers/power/domain/altr-pmgr-agilex5.c | 112 ++++++++++++++++++
> 9 files changed, 176 insertions(+)
> create mode 100644 doc/device-tree-bindings/power/altr,pmgr-agilex5.yaml
> create mode 100644 drivers/power/domain/altr-pmgr-agilex5.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d62dd35a385..100a1c7b3cd 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -156,6 +156,7 @@ M: Tingting Meng <tingting.m...@altera.com>
> S: Maintained
> T: git https://source.denx.de/u-boot/custodians/u-boot-socfpga.git
> F: drivers/ddr/altera/
> +F: drivers/power/domain/altr-pmgr-agilex5.c
> F: arch/arm/mach-socfpga/
> F: configs/socfpga_agilex5_vab_defconfig
> F: drivers/sysreset/sysreset_socfpga*
> diff --git a/arch/arm/dts/socfpga_agilex5-u-boot.dtsi
> b/arch/arm/dts/socfpga_agilex5-u-boot.dtsi
> index 874e71b5ca4..402f0bec173 100644
> --- a/arch/arm/dts/socfpga_agilex5-u-boot.dtsi
> +++ b/arch/arm/dts/socfpga_agilex5-u-boot.dtsi
> @@ -668,6 +668,12 @@
> bootph-all;
> };
> };
> +
> + pwrmgr: pwrmgr@10d14000 {
> + compatible = "altr,pmgr-agilex5";
> + reg = <0x10d14000 0x100>;
> + bootph-all;
> + };
> };
> };
>
> diff --git a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
> b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
> index 763b077d8c1..04203cceb8a 100644
> --- a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
> +++ b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
> @@ -68,6 +68,7 @@
> #define SOC64_HANDOFF_CLOCK (SOC64_HANDOFF_BASE +
> 0x580)
> #if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
> #define SOC64_HANDOFF_PERI (SOC64_HANDOFF_BASE + 0x620)
> +#define SOC64_HANDOFF_PERI_LEN 1
> #define SOC64_HANDOFF_SDRAM (SOC64_HANDOFF_BASE +
> 0x634)
> #define SOC64_HANDOFF_SDRAM_LEN 5
> #endif
> diff --git a/arch/arm/mach-socfpga/spl_agilex5.c b/arch/arm/mach-
> socfpga/spl_agilex5.c
> index a9aad5350d2..2a13301802d 100644
> --- a/arch/arm/mach-socfpga/spl_agilex5.c
> +++ b/arch/arm/mach-socfpga/spl_agilex5.c
> @@ -96,6 +96,12 @@ void board_init_f(ulong dummy)
> hang();
> }
>
> + ret = uclass_get_device(UCLASS_POWER_DOMAIN, 0, &dev);
> + if (ret) {
> + debug("PSS SRAM power-off failed: %d\n", ret);
> + hang();
> + }
> +
> if (IS_ENABLED(CONFIG_SPL_ALTERA_SDRAM)) {
> ret = uclass_get_device(UCLASS_RAM, 0, &dev);
> if (ret) {
> diff --git a/configs/socfpga_agilex5_defconfig
> b/configs/socfpga_agilex5_defconfig
> index 4ac0a5d9b99..5e8f2b85fc1 100644
> --- a/configs/socfpga_agilex5_defconfig
> +++ b/configs/socfpga_agilex5_defconfig
> @@ -103,3 +103,5 @@ CONFIG_DESIGNWARE_WATCHDOG=y
> CONFIG_WDT=y # CONFIG_SPL_USE_TINY_PRINTF is not set
> CONFIG_PANIC_HANG=y
> +CONFIG_SPL_POWER_DOMAIN=y
> +CONFIG_AGILEX5_PMGR_POWER_DOMAIN=y
> diff --git a/doc/device-tree-bindings/power/altr,pmgr-agilex5.yaml
> b/doc/device-tree-bindings/power/altr,pmgr-agilex5.yaml
> new file mode 100644
> index 00000000000..af7aeaa922c
> --- /dev/null
> +++ b/doc/device-tree-bindings/power/altr,pmgr-agilex5.yaml
> @@ -0,0 +1,39 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2
> +---
> +$id: "http://devicetree.org/schemas/power/altr,pmgr-agilex5.yaml#"
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#"
> +
> +title: Altera Agilex5 Power Manager
> +
> +maintainers:
> + - name: Alif Zakuan Yuslaimi
> + email: alif.zakuan.yusla...@altera.com
> +
> +description: |
> + This controller will read the peripheral handoff data obtained from
> +the
> + bitstream and will power gate the specified peripheral's SRAM from
> +the
> + handoff data values to reduce power consumption.
> +
> +properties:
> + compatible:
> + const: "altr,pmgr-agilex5"
> +
> + reg:
> + maxItems: 1
> +
> + bootph-all: true
> +
> +required:
> + - compatible
> + - reg
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + pwrmgr: pwrmgr@10d14000 {
> + compatible = "altr,pmgr-agilex5";
> + reg = <0x10d14000 0x100>;
> + bootph-all;
> + };
> diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
> index 5f5218bd8b5..ebf5d828cb0 100644
> --- a/drivers/power/domain/Kconfig
> +++ b/drivers/power/domain/Kconfig
> @@ -18,6 +18,14 @@ config APPLE_PMGR_POWER_DOMAIN
> This driver is needed to power on parts of the SoC that have
> not been powered on by previous boot stages.
>
> +config AGILEX5_PMGR_POWER_DOMAIN
> + bool "Enable the Agilex5 PMGR power domain driver"
> + depends on SPL_POWER_DOMAIN
> + help
> + Enable support for power gating peripherals' SRAM specified in
> + the handoff data values obtained from the bitstream to reduce
> + power consumption.
> +
> config BCM6328_POWER_DOMAIN
> bool "Enable the BCM6328 power domain driver"
> depends on POWER_DOMAIN && ARCH_BMIPS
> diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
> index 4d20c97d26c..8e03f620437 100644
> --- a/drivers/power/domain/Makefile
> +++ b/drivers/power/domain/Makefile
> @@ -5,6 +5,7 @@
>
> obj-$(CONFIG_$(PHASE_)POWER_DOMAIN) += power-domain-uclass.o
> obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
> +obj-$(CONFIG_AGILEX5_PMGR_POWER_DOMAIN) += altr-pmgr-agilex5.o
> obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
> obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o
> imx8-power-domain.o
> obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o diff --
> git a/drivers/power/domain/altr-pmgr-agilex5.c b/drivers/power/domain/altr-
> pmgr-agilex5.c
> new file mode 100644
> index 00000000000..257e8b234fd
> --- /dev/null
> +++ b/drivers/power/domain/altr-pmgr-agilex5.c
> @@ -0,0 +1,112 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2025 Altera Corporation <www.altera.com> */
> +
> +#include <dm.h>
> +#include <power-domain-uclass.h>
> +#include <asm/io.h>
> +#include <asm/arch/handoff_soc64.h>
> +#include <linux/bitfield.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <time.h>
> +
> +#define PSS_FWENCTL 0x44
> +#define PSS_PGENCTL 0x48
> +#define PSS_PGSTAT 0x4c
> +
> +#define DATA_MASK GENMASK(7, 0)
> +#define TIMEOUT_MS 1000
> +
> +static int wait_verify_fsm(u16 timeout_ms, uintptr_t base_addr, u32
> +peripheral_handoff) {
> + u32 data = 0;
> + u32 pgstat = 0;
> + ulong start = get_timer(0);
> +
> + /* Wait FSM ready */
> + do {
> + data = FIELD_GET(DATA_MASK, readl(base_addr +
> PSS_PGSTAT));
> + if (data != 0)
> + break;
> + } while (get_timer(start) < timeout_ms);
> +
> + if (get_timer(start) >= timeout_ms)
> + return -ETIMEDOUT;
> +
> + /* Verify PSS SRAM power gated */
> + pgstat = FIELD_GET(DATA_MASK, readl(base_addr + PSS_PGSTAT));
> + if (pgstat != FIELD_GET(DATA_MASK, peripheral_handoff))
> + return -EPERM;
> +
> + return 0;
> +}
> +
> +static int pss_sram_power_off(uintptr_t base_addr, u32 *handoff_table)
> +{
> + u32 peripheral_handoff;
> +
> + /* Get PSS SRAM handoff data */
> + peripheral_handoff = handoff_table[0];
> +
> + /* Enable firewall for PSS SRAM */
> + setbits_le32(base_addr + PSS_FWENCTL, peripheral_handoff);
> +
> + /* Wait */
> + udelay(1);
> +
> + /* Power gating PSS SRAM */
> + setbits_le32(base_addr + PSS_PGENCTL, peripheral_handoff);
> +
> + return wait_verify_fsm(TIMEOUT_MS, base_addr,
> peripheral_handoff); }
> +
> +static int altera_pmgr_off(struct power_domain *power_domain) {
> + fdt_addr_t base_addr = dev_read_addr(power_domain->dev);
> + u32 handoff_table[SOC64_HANDOFF_PERI_LEN];
> + int ret;
> +
> + /* Read handoff data for peripherals configuration */
> + ret = socfpga_handoff_read((void *)SOC64_HANDOFF_PERI,
> handoff_table,
> + SOC64_HANDOFF_PERI_LEN);
> + if (ret) {
> + debug("%s: handoff data read failed. ret: %d\n", __func__, ret);
> + return ret;
> + }
> +
> + pss_sram_power_off(base_addr, handoff_table);
> +
> + return 0;
> +}
> +
> +static int altera_pmgr_probe(struct udevice *dev) {
> + struct power_domain *power_domain = dev_get_priv(dev);
> +
> + if (!power_domain)
> + return -EINVAL;
> +
> + power_domain->dev = dev;
> +
> + return altera_pmgr_off(power_domain);
> +}
> +
> +static const struct udevice_id altera_pmgr_ids[] = {
> + { .compatible = "altr,pmgr-agilex5" },
> + { /* sentinel */ }
> +};
> +
> +static struct power_domain_ops altera_pmgr_ops = {
> + .off = altera_pmgr_off,
> +};
> +
> +U_BOOT_DRIVER(altr_pmgr) = {
> + .name = "altr_pmgr",
> + .id = UCLASS_POWER_DOMAIN,
> + .of_match = altera_pmgr_ids,
> + .ops = &altera_pmgr_ops,
> + .probe = altera_pmgr_probe,
> + .priv_auto = sizeof(struct power_domain), };
> --
> 2.25.1
Reviewed-by: Tien Fong Chee <tien.fong.c...@altera.com>
Best regards,
Tien Fong