arch: arm: agilex5: Enable power manager for Agilex5

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>
This commit is contained in:
Alif Zakuan Yuslaimi 2025-06-12 01:08:00 -07:00 committed by Tien Fong Chee
parent 5119cffaf4
commit 9f68908686
9 changed files with 176 additions and 0 deletions

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

View File

@ -668,6 +668,12 @@
bootph-all;
};
};
pwrmgr: pwrmgr@10d14000 {
compatible = "altr,pmgr-agilex5";
reg = <0x10d14000 0x100>;
bootph-all;
};
};
};

View 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

View 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) {

View 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

View File

@ -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;
};

View 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

View 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

View File

@ -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),
};