diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clk/altera/clk-n5x.c | 4 | ||||
| -rw-r--r-- | drivers/ddr/altera/sdram_n5x.c | 8 | ||||
| -rw-r--r-- | drivers/fpga/socfpga_gen5.c | 25 | ||||
| -rw-r--r-- | drivers/misc/socfpga_dtreg.c | 5 | ||||
| -rw-r--r-- | drivers/power/domain/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/power/domain/Makefile | 1 | ||||
| -rw-r--r-- | drivers/power/domain/altr-pmgr-agilex5.c | 112 |
7 files changed, 135 insertions, 28 deletions
diff --git a/drivers/clk/altera/clk-n5x.c b/drivers/clk/altera/clk-n5x.c index 09db250ab6d..9e4e7a1d908 100644 --- a/drivers/clk/altera/clk-n5x.c +++ b/drivers/clk/altera/clk-n5x.c @@ -386,8 +386,8 @@ static u32 clk_get_emac_clk_hz(struct socfpga_clk_plat *plat, u32 emac_id) } else { clock /= 1 + ((CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) & - CLKMGR_PLLOUTDIV_C3CNT_MASK >> - CLKMGR_PLLOUTDIV_C3CNT_OFFSET)); + CLKMGR_PLLOUTDIV_C3CNT_MASK) >> + CLKMGR_PLLOUTDIV_C3CNT_OFFSET); } break; diff --git a/drivers/ddr/altera/sdram_n5x.c b/drivers/ddr/altera/sdram_n5x.c index d1fc93b6bdd..17ec6afa82b 100644 --- a/drivers/ddr/altera/sdram_n5x.c +++ b/drivers/ddr/altera/sdram_n5x.c @@ -346,25 +346,25 @@ struct ddr_handoff { phys_addr_t cntlr_base; size_t cntlr_total_length; enum ddr_type cntlr_t; - size_t cntlr_handoff_length; + int cntlr_handoff_length; /* Second controller attributes*/ phys_addr_t cntlr2_handoff_base; phys_addr_t cntlr2_base; size_t cntlr2_total_length; enum ddr_type cntlr2_t; - size_t cntlr2_handoff_length; + int cntlr2_handoff_length; /* PHY attributes */ phys_addr_t phy_handoff_base; phys_addr_t phy_base; size_t phy_total_length; - size_t phy_handoff_length; + int phy_handoff_length; /* PHY engine attributes */ phys_addr_t phy_engine_handoff_base; size_t phy_engine_total_length; - size_t phy_engine_handoff_length; + int phy_engine_handoff_length; /* Calibration attributes */ phys_addr_t train_imem_base; diff --git a/drivers/fpga/socfpga_gen5.c b/drivers/fpga/socfpga_gen5.c index 9473f057328..964a5cc8789 100644 --- a/drivers/fpga/socfpga_gen5.c +++ b/drivers/fpga/socfpga_gen5.c @@ -119,27 +119,14 @@ static int fpgamgr_program_poll_cd(void) { const uint32_t mask = FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK | FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK; - unsigned long reg, i; + unsigned long reg; - /* (3) wait until full config done */ - for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { - reg = readl(&fpgamgr_regs->gpio_ext_porta); - - /* Config error */ - if (!(reg & mask)) { - printf("FPGA: Configuration error.\n"); - return -3; - } - - /* Config done without error */ - if (reg & mask) - break; - } + reg = readl(&fpgamgr_regs->gpio_ext_porta); - /* Timeout happened, return error */ - if (i == FPGA_TIMEOUT_CNT) { - printf("FPGA: Timeout waiting for program.\n"); - return -4; + /* Config error */ + if (!(reg & mask)) { + printf("FPGA: Configuration error.\n"); + return -3; } /* Disable AXI configuration */ diff --git a/drivers/misc/socfpga_dtreg.c b/drivers/misc/socfpga_dtreg.c index ea5d0bcdf51..dd6809433e3 100644 --- a/drivers/misc/socfpga_dtreg.c +++ b/drivers/misc/socfpga_dtreg.c @@ -76,16 +76,15 @@ static int socfpga_dtreg_probe(struct udevice *dev) return -EINVAL; } + reg = base + offset; + if (mask != 0) { if (mask == 0xffffffff) { - reg = base + offset; writel(val, (uintptr_t)reg); } else { /* Mask the value with the masking bits */ set_mask = val & mask; - reg = base + offset; - /* Clears and sets specific bits in the register */ clrsetbits_le32((uintptr_t)reg, mask, set_mask); } 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), +}; |
