[PATCH v1] arch: arm: agilex5: Enable power manager for Agilex5
alif.zakuan.yuslaimi at altera.com
alif.zakuan.yuslaimi at altera.com
Thu Jun 12 10:08:00 CEST 2025
From: Alif Zakuan Yuslaimi <alif.zakuan.yuslaimi at 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.yuslaimi at 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.meng at 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 at 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.yuslaimi at 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 at 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
More information about the U-Boot
mailing list