]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
arch: arm: agilex5: Enable power manager for Agilex5
authorAlif Zakuan Yuslaimi <alif.zakuan.yuslaimi@altera.com>
Thu, 12 Jun 2025 08:08:00 +0000 (01:08 -0700)
committerTien Fong Chee <tien.fong.chee@intel.com>
Wed, 30 Jul 2025 09:45:31 +0000 (17:45 +0800)
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@altera.com>
Reviewed-by: Tien Fong Chee <tien.fong.chee@altera.com>
MAINTAINERS
arch/arm/dts/socfpga_agilex5-u-boot.dtsi
arch/arm/mach-socfpga/include/mach/handoff_soc64.h
arch/arm/mach-socfpga/spl_agilex5.c
configs/socfpga_agilex5_defconfig
doc/device-tree-bindings/power/altr,pmgr-agilex5.yaml [new file with mode: 0644]
drivers/power/domain/Kconfig
drivers/power/domain/Makefile
drivers/power/domain/altr-pmgr-agilex5.c [new file with mode: 0644]

index c4eaba58a9013d2ef038a11a593cbe5590f3c3e3..795ff2328dd79a035099a3f90e246310e13ff96b 100644 (file)
@@ -156,6 +156,7 @@ M:  Tingting Meng <tingting.meng@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*
index 874e71b5ca4b995fff52a0c8b0d16d0324224a33..402f0bec173d64a8384aa5ecdbf161018b042b8d 100644 (file)
                                bootph-all;
                        };
                };
+
+               pwrmgr: pwrmgr@10d14000 {
+                       compatible = "altr,pmgr-agilex5";
+                       reg = <0x10d14000 0x100>;
+                       bootph-all;
+               };
        };
 };
 
index 763b077d8c1892766d701f8a7b2888442314b16c..04203cceb8a654fe8937ba8142ddac68056c7933 100644 (file)
@@ -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
index a9aad5350d25fb6d6d65e89402901f43471bdb76..2a13301802d21525e66a7c8215df8525160b23d8 100644 (file)
@@ -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) {
index 33a6221979a4231502f5040f702316beeb4823f3..7dbb1b4aa4ed5e6efe4dff4e5e52501c32a7b21f 100644 (file)
@@ -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 (file)
index 0000000..af7aeaa
--- /dev/null
@@ -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@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;
+    };
index 5f5218bd8b5f4bed8283e91da61ac7c8c3eb97ae..ebf5d828cb021e1a0f98f97c1d8891c388b6c599 100644 (file)
@@ -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
index 4d20c97d26c0a1a545390a780ea86456d895ffe6..8e03f620437edc6f3d39922b0d5c972fdcd57801 100644 (file)
@@ -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 (file)
index 0000000..257e8b2
--- /dev/null
@@ -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),
+};