diff options
Diffstat (limited to 'Documentation/driver-api/fpga/fpga-mgr.rst')
-rw-r--r-- | Documentation/driver-api/fpga/fpga-mgr.rst | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst new file mode 100644 index 000000000000..bcf2dd24e179 --- /dev/null +++ b/Documentation/driver-api/fpga/fpga-mgr.rst | |||
@@ -0,0 +1,220 @@ | |||
1 | FPGA Manager | ||
2 | ============ | ||
3 | |||
4 | Overview | ||
5 | -------- | ||
6 | |||
7 | The FPGA manager core exports a set of functions for programming an FPGA with | ||
8 | an image. The API is manufacturer agnostic. All manufacturer specifics are | ||
9 | hidden away in a low level driver which registers a set of ops with the core. | ||
10 | The FPGA image data itself is very manufacturer specific, but for our purposes | ||
11 | it's just binary data. The FPGA manager core won't parse it. | ||
12 | |||
13 | The FPGA image to be programmed can be in a scatter gather list, a single | ||
14 | contiguous buffer, or a firmware file. Because allocating contiguous kernel | ||
15 | memory for the buffer should be avoided, users are encouraged to use a scatter | ||
16 | gather list instead if possible. | ||
17 | |||
18 | The particulars for programming the image are presented in a structure (struct | ||
19 | fpga_image_info). This struct contains parameters such as pointers to the | ||
20 | FPGA image as well as image-specific particulars such as whether the image was | ||
21 | built for full or partial reconfiguration. | ||
22 | |||
23 | How to support a new FPGA device | ||
24 | -------------------------------- | ||
25 | |||
26 | To add another FPGA manager, write a driver that implements a set of ops. The | ||
27 | probe function calls fpga_mgr_register(), such as:: | ||
28 | |||
29 | static const struct fpga_manager_ops socfpga_fpga_ops = { | ||
30 | .write_init = socfpga_fpga_ops_configure_init, | ||
31 | .write = socfpga_fpga_ops_configure_write, | ||
32 | .write_complete = socfpga_fpga_ops_configure_complete, | ||
33 | .state = socfpga_fpga_ops_state, | ||
34 | }; | ||
35 | |||
36 | static int socfpga_fpga_probe(struct platform_device *pdev) | ||
37 | { | ||
38 | struct device *dev = &pdev->dev; | ||
39 | struct socfpga_fpga_priv *priv; | ||
40 | struct fpga_manager *mgr; | ||
41 | int ret; | ||
42 | |||
43 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
44 | if (!priv) | ||
45 | return -ENOMEM; | ||
46 | |||
47 | /* | ||
48 | * do ioremaps, get interrupts, etc. and save | ||
49 | * them in priv | ||
50 | */ | ||
51 | |||
52 | mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", | ||
53 | &socfpga_fpga_ops, priv); | ||
54 | if (!mgr) | ||
55 | return -ENOMEM; | ||
56 | |||
57 | platform_set_drvdata(pdev, mgr); | ||
58 | |||
59 | ret = fpga_mgr_register(mgr); | ||
60 | if (ret) | ||
61 | fpga_mgr_free(mgr); | ||
62 | |||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | static int socfpga_fpga_remove(struct platform_device *pdev) | ||
67 | { | ||
68 | struct fpga_manager *mgr = platform_get_drvdata(pdev); | ||
69 | |||
70 | fpga_mgr_unregister(mgr); | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | |||
76 | The ops will implement whatever device specific register writes are needed to | ||
77 | do the programming sequence for this particular FPGA. These ops return 0 for | ||
78 | success or negative error codes otherwise. | ||
79 | |||
80 | The programming sequence is:: | ||
81 | 1. .write_init | ||
82 | 2. .write or .write_sg (may be called once or multiple times) | ||
83 | 3. .write_complete | ||
84 | |||
85 | The .write_init function will prepare the FPGA to receive the image data. The | ||
86 | buffer passed into .write_init will be atmost .initial_header_size bytes long, | ||
87 | if the whole bitstream is not immediately available then the core code will | ||
88 | buffer up at least this much before starting. | ||
89 | |||
90 | The .write function writes a buffer to the FPGA. The buffer may be contain the | ||
91 | whole FPGA image or may be a smaller chunk of an FPGA image. In the latter | ||
92 | case, this function is called multiple times for successive chunks. This interface | ||
93 | is suitable for drivers which use PIO. | ||
94 | |||
95 | The .write_sg version behaves the same as .write except the input is a sg_table | ||
96 | scatter list. This interface is suitable for drivers which use DMA. | ||
97 | |||
98 | The .write_complete function is called after all the image has been written | ||
99 | to put the FPGA into operating mode. | ||
100 | |||
101 | The ops include a .state function which will read the hardware FPGA manager and | ||
102 | return a code of type enum fpga_mgr_states. It doesn't result in a change in | ||
103 | hardware state. | ||
104 | |||
105 | How to write an image buffer to a supported FPGA | ||
106 | ------------------------------------------------ | ||
107 | |||
108 | Some sample code:: | ||
109 | |||
110 | #include <linux/fpga/fpga-mgr.h> | ||
111 | |||
112 | struct fpga_manager *mgr; | ||
113 | struct fpga_image_info *info; | ||
114 | int ret; | ||
115 | |||
116 | /* | ||
117 | * Get a reference to FPGA manager. The manager is not locked, so you can | ||
118 | * hold onto this reference without it preventing programming. | ||
119 | * | ||
120 | * This example uses the device node of the manager. Alternatively, use | ||
121 | * fpga_mgr_get(dev) instead if you have the device. | ||
122 | */ | ||
123 | mgr = of_fpga_mgr_get(mgr_node); | ||
124 | |||
125 | /* struct with information about the FPGA image to program. */ | ||
126 | info = fpga_image_info_alloc(dev); | ||
127 | |||
128 | /* flags indicates whether to do full or partial reconfiguration */ | ||
129 | info->flags = FPGA_MGR_PARTIAL_RECONFIG; | ||
130 | |||
131 | /* | ||
132 | * At this point, indicate where the image is. This is pseudo-code; you're | ||
133 | * going to use one of these three. | ||
134 | */ | ||
135 | if (image is in a scatter gather table) { | ||
136 | |||
137 | info->sgt = [your scatter gather table] | ||
138 | |||
139 | } else if (image is in a buffer) { | ||
140 | |||
141 | info->buf = [your image buffer] | ||
142 | info->count = [image buffer size] | ||
143 | |||
144 | } else if (image is in a firmware file) { | ||
145 | |||
146 | info->firmware_name = devm_kstrdup(dev, firmware_name, GFP_KERNEL); | ||
147 | |||
148 | } | ||
149 | |||
150 | /* Get exclusive control of FPGA manager */ | ||
151 | ret = fpga_mgr_lock(mgr); | ||
152 | |||
153 | /* Load the buffer to the FPGA */ | ||
154 | ret = fpga_mgr_buf_load(mgr, &info, buf, count); | ||
155 | |||
156 | /* Release the FPGA manager */ | ||
157 | fpga_mgr_unlock(mgr); | ||
158 | fpga_mgr_put(mgr); | ||
159 | |||
160 | /* Deallocate the image info if you're done with it */ | ||
161 | fpga_image_info_free(info); | ||
162 | |||
163 | API for implementing a new FPGA Manager driver | ||
164 | ---------------------------------------------- | ||
165 | |||
166 | .. kernel-doc:: include/linux/fpga/fpga-mgr.h | ||
167 | :functions: fpga_manager | ||
168 | |||
169 | .. kernel-doc:: include/linux/fpga/fpga-mgr.h | ||
170 | :functions: fpga_manager_ops | ||
171 | |||
172 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
173 | :functions: fpga_mgr_create | ||
174 | |||
175 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
176 | :functions: fpga_mgr_free | ||
177 | |||
178 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
179 | :functions: fpga_mgr_register | ||
180 | |||
181 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
182 | :functions: fpga_mgr_unregister | ||
183 | |||
184 | API for programming a FPGA | ||
185 | -------------------------- | ||
186 | |||
187 | .. kernel-doc:: include/linux/fpga/fpga-mgr.h | ||
188 | :functions: fpga_image_info | ||
189 | |||
190 | .. kernel-doc:: include/linux/fpga/fpga-mgr.h | ||
191 | :functions: fpga_mgr_states | ||
192 | |||
193 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
194 | :functions: fpga_image_info_alloc | ||
195 | |||
196 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
197 | :functions: fpga_image_info_free | ||
198 | |||
199 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
200 | :functions: of_fpga_mgr_get | ||
201 | |||
202 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
203 | :functions: fpga_mgr_get | ||
204 | |||
205 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
206 | :functions: fpga_mgr_put | ||
207 | |||
208 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
209 | :functions: fpga_mgr_lock | ||
210 | |||
211 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
212 | :functions: fpga_mgr_unlock | ||
213 | |||
214 | .. kernel-doc:: include/linux/fpga/fpga-mgr.h | ||
215 | :functions: fpga_mgr_states | ||
216 | |||
217 | Note - use :c:func:`fpga_region_program_fpga()` instead of :c:func:`fpga_mgr_load()` | ||
218 | |||
219 | .. kernel-doc:: drivers/fpga/fpga-mgr.c | ||
220 | :functions: fpga_mgr_load | ||