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

Reply via email to