diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index ce861a2..aa50fa4 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -20,6 +20,13 @@ config FPGA_REGION
 	  FPGA Regions allow loading FPGA images under control of
 	  the Device Tree.
 
+config FPGA_MGR_A10_PCIE_PR
+	tristate "Arria 10 partial reconfiguration over PCIe PR IP"
+	depends on PCI
+	help
+	  FPGA manager driver support for Arria 10 partial
+	  reconfiguration over PCIe
+
 config FPGA_MGR_SOCFPGA
 	tristate "Altera SOCFPGA FPGA Manager"
 	depends on ARCH_SOCFPGA || COMPILE_TEST
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 8df07bc..b90b3f5 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_FPGA)			+= fpga-mgr.o
 
 # FPGA Manager Drivers
+obj-$(CONFIG_FPGA_MGR_A10_PCIE_PR)	+= a10-pcie-pr.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10)	+= socfpga-a10.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
diff --git a/drivers/fpga/a10-pcie-pr.c b/drivers/fpga/a10-pcie-pr.c
new file mode 100644
index 0000000..09de181
--- /dev/null
+++ b/drivers/fpga/a10-pcie-pr.c
@@ -0,0 +1,299 @@
+/*
+ * FPGA Manager Driver for Arria 10 partial reconfiguration over PCIe.
+ * Firmware must be in binary "rbf" format.
+ *
+ * Copyright (C) 2017 DENX Software Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+
+#define DRV_NAME		"a10-pcie-pr"
+#define PCIE_PR_MGR_NAME	"PCIe PR Manager"
+#define DFLT_FIRMWARE_STR	"a10_pr_region.rbf"
+#define PR_IP_BAR		4	/* PCIe PR IP core BAR */
+#define PR_CONTROLLER_OFFSET	0xcfb0
+#define CMD_PR			0x01
+#define CMD_DOUBLE_PR		0x03
+
+static char firmware[NAME_MAX];
+module_param_string(firmware, firmware, sizeof(firmware), 0444);
+MODULE_PARM_DESC(firmware, " RBF file in /lib/firmware to load via PCIe PR");
+
+/* use value 1 for debugging only */
+static int chkcfg;
+module_param(chkcfg, int, 0664);
+MODULE_PARM_DESC(chkcfg, " 1 - check error status, 0 - skip check (default 0)");
+
+/* PR IP core registers */
+struct pr_regs {
+	u32	pr_data;
+	u32	pr_csr;
+};
+
+struct pcie_pr_conf {
+	struct fpga_manager	*mgr;
+	struct pci_dev		*pci_dev;
+	struct pr_regs		*regs;
+	void __iomem		*map;
+	u32			fw_size;
+};
+
+static enum fpga_mgr_states pcie_pr_state(struct fpga_manager *mgr)
+{
+	return mgr->state;
+}
+
+static int pcie_pr_write_init(struct fpga_manager *mgr,
+			      struct fpga_image_info *info,
+			      const char *buf, size_t count)
+{
+	struct pcie_pr_conf *conf = mgr->priv;
+	u32 status;
+
+	if (info)
+		dev_dbg(&mgr->dev, "%s(): flags 0x%x\n", __func__, info->flags);
+
+	if (info && !(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+		dev_err(&mgr->dev, "Only partial reconfiguration supported.\n");
+		return -EINVAL;
+	}
+
+	status = readl(&conf->regs->pr_csr);
+	dev_dbg(&mgr->dev, "PR IP status 0x%08X\n", status);
+
+	dev_dbg(&mgr->dev, "PR IP command 0x%08X\n", CMD_PR);
+	writel(CMD_PR, &conf->regs->pr_csr);
+
+	status = readl(&conf->regs->pr_csr);
+	dev_dbg(&mgr->dev, "PR IP status: 0x%08X\n", (int) status);
+	if ((status != 0x10) && (status != 0x0)) {
+		dev_err(&mgr->dev, "status 0x%x\n", status);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int pcie_pr_write(struct fpga_manager *mgr, const char *buf,
+			 size_t count)
+{
+	struct pcie_pr_conf *conf = mgr->priv;
+	const u32 *data, *data_end;
+	size_t bytes = 0;
+	int ret = 0;
+	int status;
+
+	dev_dbg(&mgr->dev, "%s: count %li\n", __func__, count);
+
+	conf->fw_size = 0;
+	data = (u32 *)buf;
+	data_end = (u32 *)((char *)buf + count);
+
+	while (data < data_end) {
+		writel(*data++, &conf->regs->pr_data);
+		bytes += 4;
+		if (chkcfg) {
+			status = readl(&conf->regs->pr_csr) >> 2;
+			switch (status) {
+			case 1 ... 3:
+				dev_err(&mgr->dev, "PR error: 0x%x\n", status);
+				ret = -EIO;
+				break;
+			}
+		}
+	}
+
+	dev_dbg(&mgr->dev, "PR bytes written: %li\n", bytes);
+
+	if (!ret) {
+		/*
+		 * remember the loaded rbf image size to show this
+		 * info via sysfs firmware file when reading it
+		 */
+		conf->fw_size = count;
+	}
+
+	return ret;
+}
+
+static int pcie_pr_write_complete(struct fpga_manager *mgr,
+				  struct fpga_image_info *info)
+{
+	struct pcie_pr_conf *conf = mgr->priv;
+	int status = 0;
+
+	dev_dbg(&mgr->dev, "%s\n", __func__);
+
+	status = readl(&conf->regs->pr_csr);
+	if (status == 0x14) {
+		dev_dbg(&mgr->dev, "PR done: 0x%08X\n", status);
+		return 0;
+	}
+
+	dev_err(&mgr->dev, "PR error: 0x%08X\n", status);
+
+	return -EIO;
+}
+
+static const struct fpga_manager_ops pcie_pr_ops = {
+	.state		= pcie_pr_state,
+	.write_init	= pcie_pr_write_init,
+	.write		= pcie_pr_write,
+	.write_complete	= pcie_pr_write_complete,
+};
+
+static ssize_t show_firmware(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	struct pcie_pr_conf *conf = mgr->priv;
+
+	return snprintf(buf, PAGE_SIZE, "%s %i\n",
+			firmware, conf->fw_size);
+}
+
+static ssize_t store_firmware(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	int ret;
+
+	if (!count || count > NAME_MAX)
+		return -EINVAL;
+
+	ret = sscanf(buf, "%s", firmware);
+	if (ret != 1)
+		return -EINVAL;
+
+	ret = fpga_mgr_firmware_load(mgr, NULL, firmware);
+
+	return ret ? ret : count;
+}
+
+static DEVICE_ATTR(firmware, 0664, show_firmware, store_firmware);
+
+static int pcie_pr_probe(struct pci_dev *pdev,
+			 const struct pci_device_id *dev_id)
+{
+	struct pcie_pr_conf *conf;
+	int ret;
+
+	dev_dbg(&pdev->dev, "%s\n", __func__);
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "can't enable pci device: %d\n", ret);
+		return ret;
+	}
+
+	pci_set_master(pdev);
+
+	conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL);
+	if (!conf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	conf->pci_dev = pdev;
+
+	if (pci_request_region(pdev, PR_IP_BAR, "PR IP") < 0) {
+		dev_err(&pdev->dev, "Requesting PR BAR region failed\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	conf->map = pci_iomap(pdev, PR_IP_BAR, 0);
+	if (!conf->map) {
+		dev_warn(&pdev->dev, "Mapping PR BAR failed\n");
+		ret = -ENODEV;
+		goto err_reg;
+	}
+
+	conf->regs = conf->map + PR_CONTROLLER_OFFSET;
+
+	ret = fpga_mgr_register(&pdev->dev, PCIE_PR_MGR_NAME,
+				&pcie_pr_ops, conf);
+	if (ret)
+		goto err_unmap;
+
+	conf->mgr = fpga_mgr_get(&pdev->dev);
+	if (IS_ERR(conf->mgr)) {
+		dev_err(&pdev->dev, "Getting fpga-mgr reference failed\n");
+		ret = -ENODEV;
+		goto err_mgr;
+	}
+
+	if (!strnlen(firmware, NAME_MAX))
+		strncpy(firmware, DFLT_FIRMWARE_STR, sizeof(firmware));
+
+	ret = fpga_mgr_firmware_load(conf->mgr, NULL, firmware);
+	if (ret)
+		dev_warn(&pdev->dev, "loading fpga image failed\n");
+
+	ret = device_create_file(&conf->mgr->dev, &dev_attr_firmware);
+	if (ret)
+		dev_warn(&pdev->dev, "can't create reconfig interface %d\n",
+			 ret);
+
+	return 0;
+
+err_mgr:
+	fpga_mgr_unregister(&pdev->dev);
+err_unmap:
+	pci_iounmap(pdev, conf->map);
+err_reg:
+	pci_release_region(pdev, PR_IP_BAR);
+err:
+	pci_disable_device(pdev);
+	return ret;
+}
+
+static void pcie_pr_remove(struct pci_dev *pdev)
+{
+	struct fpga_manager *mgr = pci_get_drvdata(pdev);
+	struct pcie_pr_conf *conf = mgr->priv;
+
+	fpga_mgr_put(conf->mgr);
+	fpga_mgr_unregister(&pdev->dev);
+	pci_iounmap(pdev, conf->map);
+	pci_release_region(pdev, PR_IP_BAR);
+	pci_disable_device(pdev);
+}
+
+#define PCI_VENDOR_ID_ALTERA	0x1172
+#define PCI_DEVICE_ID_FPGA	0xe003
+
+static struct pci_device_id pcie_pr_id_tbl[] = {
+	{ PCI_VDEVICE(ALTERA, PCI_DEVICE_ID_FPGA) },
+	{ }
+};
+
+static struct pci_driver pcie_pr_driver = {
+	.name   = DRV_NAME,
+	.id_table = pcie_pr_id_tbl,
+	.probe  = pcie_pr_probe,
+	.remove = pcie_pr_remove,
+};
+
+module_pci_driver(pcie_pr_driver)
+
+MODULE_DEVICE_TABLE(pci, pcie_pr_id_tbl);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
+MODULE_DESCRIPTION("Arria 10 FPGA reconfiguration via PCIe PR IP");
