[PATCH 1/1] drivers: fpga: Add partial reconfiguration console commands

Simon Glass sjg at chromium.org
Fri Mar 14 15:45:07 CET 2025


Hi,

On Fri, 14 Mar 2025 at 11:48, Naresh Kumar Ravulapalli
<nareshkumar.ravulapalli at altera.com> wrote:
>
> 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.ravulapalli at 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

Please can you put commands in cmd/ and add doc/ and test/ for them?

Also, we should have a generic FPGA API for this sort of thing.

>
> 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
> +       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], &region, 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
>

Regards,
Simon


More information about the U-Boot mailing list