> -----Original Message-----
> From: Ravulapalli, Naresh Kumar <naresh.kumar.ravulapa...@altera.com>
> Sent: Friday, March 14, 2025 7:48 PM
> To: u-boot@lists.denx.de
> Cc: Marek Vasut <ma...@denx.de>; Simon Goldschmidt
> <simon.k.r.goldschm...@gmail.com>; Chee, Tien Fong
> <tien.fong.c...@altera.com>; Michal Simek <michal.si...@amd.com>;
> Tom Rini <tr...@konsulko.com>; Ravulapalli, Naresh Kumar
> <naresh.kumar.ravulapa...@altera.com>
> Subject: [PATCH 1/1] drivers: fpga: Add partial reconfiguration console
> commands
>
> Partial Reconfiguration (pr) command is added to U-Boot console. The pr
> command will use the Freeze Controller which can freeze and unfreeze the
> specified partial reconfiguration region. The pr command supports multiple
> regions for partial reconfiguration by specifying the region ID.
>
> Signed-off-by: Naresh Kumar Ravulapalli
> <nareshkumar.ravulapa...@altera.com>
> ---
> drivers/fpga/Kconfig | 9 ++
> drivers/fpga/Makefile | 1 +
> drivers/fpga/intel_pr.c | 191
> ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 201 insertions(+)
> create mode 100644 drivers/fpga/intel_pr.c
>
> diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index
> 62cb77b098..bf34d11a9d 100644
> --- a/drivers/fpga/Kconfig
> +++ b/drivers/fpga/Kconfig
> @@ -66,6 +66,15 @@ config FPGA_LATTICE
> This is used for the lattice FPGAs. Please check the source code as
> there is no documentation for this at present.
>
> +config FPGA_INTEL_PR
Change INTEL to ALTERA, please check other.
> + bool "Enable Intel FPGA Partial Reconfiguration driver"
> + depends on FPGA_ALTERA
> + help
> + Say Y here to enable the Intel FPGA Partial Reconfiguration driver
> +
> + This provides basic functionality for partial reconfiguration which
> + include the freeze controller support.
> +
> config FPGA_XILINX
> bool "Enable Xilinx FPGA drivers"
> select FPGA
> diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index
> 610c168fc3..70a8f88836 100644
> --- a/drivers/fpga/Makefile
> +++ b/drivers/fpga/Makefile
> @@ -25,4 +25,5 @@ obj-$(CONFIG_FPGA_STRATIX_V) += stratixv.o
> obj-$(CONFIG_FPGA_SOCFPGA) += socfpga.o
> obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += socfpga_gen5.o
> obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += socfpga_arria10.o
> +obj-$(CONFIG_FPGA_INTEL_PR) += intel_pr.o
> endif
> diff --git a/drivers/fpga/intel_pr.c b/drivers/fpga/intel_pr.c new file mode
> 100644 index 0000000000..ecca2c9eeb
> --- /dev/null
> +++ b/drivers/fpga/intel_pr.c
> @@ -0,0 +1,191 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 Intel Corporation */
> +
> +#include <command.h>
> +#include <errno.h>
> +#include <wait_bit.h>
> +#include <asm/global_data.h>
> +#include <asm/io.h>
> +#include <linux/bitops.h>
> +#include <linux/libfdt.h>
> +#include <fdtdec.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define FREEZE_CSR_STATUS_OFFSET 0
> +#define FREEZE_CSR_CTRL_OFFSET 4
> +#define FREEZE_CSR_ILLEGAL_REQ_OFFSET 8
> +#define FREEZE_CSR_REG_VERSION 12
> +
> +#define FREEZE_TIMEOUT 20000
> +
> +#define FREEZE_CSR_STATUS_FREEZE_REQ_DONE BIT(0)
> +#define FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE BIT(1)
> +
> +#define FREEZE_CSR_CTRL_FREEZE_REQ BIT(0)
> +#define FREEZE_CSR_CTRL_RESET_REQ BIT(1)
> +#define FREEZE_CSR_CTRL_UNFREEZE_REQ BIT(2)
> +
> +static int intel_get_freeze_br_addr(fdt_addr_t *addr, unsigned int
> +region) {
> + int offset;
> + char freeze_br[12];
> + struct fdt_resource r;
> + int ret;
> +
> + snprintf(freeze_br, sizeof(freeze_br), "freeze_br%d", region);
> +
> + const char *alias = fdt_get_alias(gd->fdt_blob, freeze_br);
> +
> + if (!alias) {
> + printf("alias %s not found in dts\n", freeze_br);
> + return -ENODEV;
> + }
> +
> + offset = fdt_path_offset(gd->fdt_blob, alias);
> + if (offset < 0) {
> + printf("%s not found in dts\n", alias);
> + return -ENODEV;
> + }
> +
> + ret = fdt_get_resource(gd->fdt_blob, offset, "reg", 0, &r);
> + if (ret) {
> + printf("%s has no 'reg' property!\n", freeze_br);
> + return ret;
> + }
> +
> + *addr = r.start;
> +
> + return ret;
> +}
> +
> +static int intel_freeze_br_req_ack(fdt_addr_t addr, u32 req_ack) {
> + u32 status, illegal, ctrl;
> + int ret = -ETIMEDOUT;
> + unsigned long start = get_timer(0);
> +
> + while (1) {
> + illegal = readl(addr + FREEZE_CSR_ILLEGAL_REQ_OFFSET);
> + if (illegal) {
> + printf("illegal request 0x%08x detected in freeze
> bridge\n",
> +illegal);
> +
> + writel(illegal, addr +
> FREEZE_CSR_ILLEGAL_REQ_OFFSET);
> +
> + illegal = readl(addr +
> FREEZE_CSR_ILLEGAL_REQ_OFFSET);
> + if (illegal)
> + printf("illegal request 0x%08x detected in
> freeze bridge are not cleared\n",
> + illegal);
> +
> + ret = -EINVAL;
> + break;
> + }
> +
> + status = readl(addr + FREEZE_CSR_STATUS_OFFSET);
> + status &= req_ack;
> + if (status) {
> + ctrl = readl(addr + FREEZE_CSR_CTRL_OFFSET);
> + printf("%s request %x acknowledged %x %x\n",
> + __func__, req_ack, status, ctrl);
> +
> + ret = 0;
> + break;
> + }
> +
> + if (get_timer(start) > FREEZE_TIMEOUT)
> + break;
> +
> + udelay(1);
> + schedule();
> + }
> +
> + return ret;
> +}
> +
> +static int intel_freeze_br_do_freeze(unsigned int region) {
> + u32 status;
> + int ret;
> + fdt_addr_t addr;
> +
> + ret = intel_get_freeze_br_addr(&addr, region);
> + if (ret)
> + return ret;
> +
> + status = readl(addr + FREEZE_CSR_STATUS_OFFSET);
> +
> + if (status & FREEZE_CSR_STATUS_FREEZE_REQ_DONE)
> + return 0;
> + else if (!(status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE))
> + return -EINVAL;
> +
> + writel(FREEZE_CSR_CTRL_FREEZE_REQ, addr +
> FREEZE_CSR_CTRL_OFFSET);
> +
> + ret = intel_freeze_br_req_ack(addr,
> FREEZE_CSR_STATUS_FREEZE_REQ_DONE);
> + if (ret)
> + writel(0, addr + FREEZE_CSR_CTRL_OFFSET);
> + else
> + writel(FREEZE_CSR_CTRL_RESET_REQ, addr +
> FREEZE_CSR_CTRL_OFFSET);
> +
> + return ret;
> +}
> +
> +static int intel_freeze_br_do_unfreeze(unsigned int region) {
> + u32 status;
> + int ret;
> + fdt_addr_t addr;
> +
> + ret = intel_get_freeze_br_addr(&addr, region);
> + if (ret)
> + return ret;
> +
> + writel(0, addr + FREEZE_CSR_CTRL_OFFSET);
> +
> + status = readl(addr + FREEZE_CSR_STATUS_OFFSET);
> +
> + if (status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE)
> + return 0;
> + else if (!(status & FREEZE_CSR_STATUS_FREEZE_REQ_DONE))
> + return -EINVAL;
> +
> + writel(FREEZE_CSR_CTRL_UNFREEZE_REQ, addr +
> FREEZE_CSR_CTRL_OFFSET);
> +
> + ret = intel_freeze_br_req_ack(addr,
> +FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE);
> +
> + writel(0, addr + FREEZE_CSR_CTRL_OFFSET);
> +
> + return ret;
> +}
> +
> +static int do_pr(struct cmd_tbl *cmdtp, int flag, int argc, char *
> +const argv[]) {
> + const char *cmd;
> + char *region;
> + unsigned int region_num = 0;
> +
> + if (argc != 2 && argc != 3)
> + return CMD_RET_USAGE;
> +
> + cmd = argv[1];
> + if (argc == 3)
> + region_num = simple_strtoul(argv[2], ®ion, 0);
> +
> + if (strcmp(cmd, "start") == 0)
> + return intel_freeze_br_do_freeze(region_num);
> + else if (strcmp(cmd, "end") == 0)
> + return intel_freeze_br_do_unfreeze(region_num);
> +
> + return CMD_RET_USAGE;
> +}
> +
> +U_BOOT_CMD(
> + pr, 3, 1, do_pr,
> + "SoCFPGA partial reconfiguration (pr) control",
> + "start [region ID]\n"
> + " - start the pr by freezing the region\n"
> + "end [region ID]\n"
> + " - end the pr by unfreezing the PR region\n"
> +);
> --
> 2.35.3