> -----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

Reply via email to