aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/fpga
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/fpga')
-rw-r--r--drivers/fpga/Kconfig9
-rw-r--r--drivers/fpga/Makefile1
-rw-r--r--drivers/fpga/dfl-afu-dma-region.c2
-rw-r--r--drivers/fpga/zynqmp-fpga.c159
4 files changed, 170 insertions, 1 deletions
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index c20445b867ae..d892f3efcd76 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -204,4 +204,13 @@ config FPGA_DFL_PCI
204 204
205 To compile this as a module, choose M here. 205 To compile this as a module, choose M here.
206 206
207config FPGA_MGR_ZYNQMP_FPGA
208 tristate "Xilinx ZynqMP FPGA"
209 depends on ARCH_ZYNQMP || COMPILE_TEST
210 help
211 FPGA manager driver support for Xilinx ZynqMP FPGAs.
212 This driver uses the processor configuration port(PCAP)
213 to configure the programmable logic(PL) through PS
214 on ZynqMP SoC.
215
207endif # FPGA 216endif # FPGA
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index c0dd4c82fbdb..312b9371742f 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_FPGA_MGR_STRATIX10_SOC) += stratix10-soc.o
17obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o 17obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o
18obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o 18obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o
19obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o 19obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
20obj-$(CONFIG_FPGA_MGR_ZYNQMP_FPGA) += zynqmp-fpga.o
20obj-$(CONFIG_ALTERA_PR_IP_CORE) += altera-pr-ip-core.o 21obj-$(CONFIG_ALTERA_PR_IP_CORE) += altera-pr-ip-core.o
21obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT) += altera-pr-ip-core-plat.o 22obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT) += altera-pr-ip-core-plat.o
22 23
diff --git a/drivers/fpga/dfl-afu-dma-region.c b/drivers/fpga/dfl-afu-dma-region.c
index e18a786fc943..c438722bf4e1 100644
--- a/drivers/fpga/dfl-afu-dma-region.c
+++ b/drivers/fpga/dfl-afu-dma-region.c
@@ -102,7 +102,7 @@ static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,
102 goto unlock_vm; 102 goto unlock_vm;
103 } 103 }
104 104
105 pinned = get_user_pages_fast(region->user_addr, npages, 1, 105 pinned = get_user_pages_fast(region->user_addr, npages, FOLL_WRITE,
106 region->pages); 106 region->pages);
107 if (pinned < 0) { 107 if (pinned < 0) {
108 ret = pinned; 108 ret = pinned;
diff --git a/drivers/fpga/zynqmp-fpga.c b/drivers/fpga/zynqmp-fpga.c
new file mode 100644
index 000000000000..f7cbaadf49ab
--- /dev/null
+++ b/drivers/fpga/zynqmp-fpga.c
@@ -0,0 +1,159 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019 Xilinx, Inc.
4 */
5
6#include <linux/dma-mapping.h>
7#include <linux/fpga/fpga-mgr.h>
8#include <linux/io.h>
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/of_address.h>
12#include <linux/string.h>
13#include <linux/firmware/xlnx-zynqmp.h>
14
15/* Constant Definitions */
16#define IXR_FPGA_DONE_MASK BIT(3)
17
18/**
19 * struct zynqmp_fpga_priv - Private data structure
20 * @dev: Device data structure
21 * @flags: flags which is used to identify the bitfile type
22 */
23struct zynqmp_fpga_priv {
24 struct device *dev;
25 u32 flags;
26};
27
28static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr,
29 struct fpga_image_info *info,
30 const char *buf, size_t size)
31{
32 struct zynqmp_fpga_priv *priv;
33
34 priv = mgr->priv;
35 priv->flags = info->flags;
36
37 return 0;
38}
39
40static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
41 const char *buf, size_t size)
42{
43 const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
44 struct zynqmp_fpga_priv *priv;
45 dma_addr_t dma_addr;
46 u32 eemi_flags = 0;
47 char *kbuf;
48 int ret;
49
50 if (!eemi_ops || !eemi_ops->fpga_load)
51 return -ENXIO;
52
53 priv = mgr->priv;
54
55 kbuf = dma_alloc_coherent(priv->dev, size, &dma_addr, GFP_KERNEL);
56 if (!kbuf)
57 return -ENOMEM;
58
59 memcpy(kbuf, buf, size);
60
61 wmb(); /* ensure all writes are done before initiate FW call */
62
63 if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
64 eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
65
66 ret = eemi_ops->fpga_load(dma_addr, size, eemi_flags);
67
68 dma_free_coherent(priv->dev, size, kbuf, dma_addr);
69
70 return ret;
71}
72
73static int zynqmp_fpga_ops_write_complete(struct fpga_manager *mgr,
74 struct fpga_image_info *info)
75{
76 return 0;
77}
78
79static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr)
80{
81 const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
82 u32 status;
83
84 if (!eemi_ops || !eemi_ops->fpga_get_status)
85 return FPGA_MGR_STATE_UNKNOWN;
86
87 eemi_ops->fpga_get_status(&status);
88 if (status & IXR_FPGA_DONE_MASK)
89 return FPGA_MGR_STATE_OPERATING;
90
91 return FPGA_MGR_STATE_UNKNOWN;
92}
93
94static const struct fpga_manager_ops zynqmp_fpga_ops = {
95 .state = zynqmp_fpga_ops_state,
96 .write_init = zynqmp_fpga_ops_write_init,
97 .write = zynqmp_fpga_ops_write,
98 .write_complete = zynqmp_fpga_ops_write_complete,
99};
100
101static int zynqmp_fpga_probe(struct platform_device *pdev)
102{
103 struct device *dev = &pdev->dev;
104 struct zynqmp_fpga_priv *priv;
105 struct fpga_manager *mgr;
106 int ret;
107
108 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
109 if (!priv)
110 return -ENOMEM;
111
112 priv->dev = dev;
113
114 mgr = devm_fpga_mgr_create(dev, "Xilinx ZynqMP FPGA Manager",
115 &zynqmp_fpga_ops, priv);
116 if (!mgr)
117 return -ENOMEM;
118
119 platform_set_drvdata(pdev, mgr);
120
121 ret = fpga_mgr_register(mgr);
122 if (ret) {
123 dev_err(dev, "unable to register FPGA manager");
124 return ret;
125 }
126
127 return 0;
128}
129
130static int zynqmp_fpga_remove(struct platform_device *pdev)
131{
132 struct fpga_manager *mgr = platform_get_drvdata(pdev);
133
134 fpga_mgr_unregister(mgr);
135
136 return 0;
137}
138
139static const struct of_device_id zynqmp_fpga_of_match[] = {
140 { .compatible = "xlnx,zynqmp-pcap-fpga", },
141 {},
142};
143
144MODULE_DEVICE_TABLE(of, zynqmp_fpga_of_match);
145
146static struct platform_driver zynqmp_fpga_driver = {
147 .probe = zynqmp_fpga_probe,
148 .remove = zynqmp_fpga_remove,
149 .driver = {
150 .name = "zynqmp_fpga_manager",
151 .of_match_table = of_match_ptr(zynqmp_fpga_of_match),
152 },
153};
154
155module_platform_driver(zynqmp_fpga_driver);
156
157MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>");
158MODULE_DESCRIPTION("Xilinx ZynqMp FPGA Manager");
159MODULE_LICENSE("GPL");