Hi, On Fri, 14 Mar 2025 at 11:48, Naresh Kumar Ravulapalli <nareshkumar.ravulapa...@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.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
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], ®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 > Regards, Simon