]>
Commit | Line | Data |
---|---|---|
e8f5fda1 AT |
1 | FPGA Manager Core |
2 | ||
3 | Alan Tull 2015 | |
4 | ||
5 | Overview | |
6 | ======== | |
7 | ||
8 | The FPGA manager core exports a set of functions for programming an FPGA with | |
9 | an image. The API is manufacturer agnostic. All manufacturer specifics are | |
10 | hidden away in a low level driver which registers a set of ops with the core. | |
11 | The FPGA image data itself is very manufacturer specific, but for our purposes | |
12 | it's just binary data. The FPGA manager core won't parse it. | |
13 | ||
14 | ||
15 | API Functions: | |
16 | ============== | |
17 | ||
18 | To program the FPGA from a file or from a buffer: | |
19 | ------------------------------------------------- | |
20 | ||
40e83578 AT |
21 | int fpga_mgr_buf_load(struct fpga_manager *mgr, |
22 | struct fpga_image_info *info, | |
e8f5fda1 AT |
23 | const char *buf, size_t count); |
24 | ||
25 | Load the FPGA from an image which exists as a buffer in memory. | |
26 | ||
40e83578 AT |
27 | int fpga_mgr_firmware_load(struct fpga_manager *mgr, |
28 | struct fpga_image_info *info, | |
e8f5fda1 AT |
29 | const char *image_name); |
30 | ||
31 | Load the FPGA from an image which exists as a file. The image file must be on | |
40e83578 AT |
32 | the firmware search path (see the firmware class documentation). If successful, |
33 | the FPGA ends up in operating mode. Return 0 on success or a negative error | |
34 | code. | |
e8f5fda1 | 35 | |
40e83578 AT |
36 | A FPGA design contained in a FPGA image file will likely have particulars that |
37 | affect how the image is programmed to the FPGA. These are contained in struct | |
38 | fpga_image_info. Currently the only such particular is a single flag bit | |
39 | indicating whether the image is for full or partial reconfiguration. | |
e8f5fda1 AT |
40 | |
41 | To get/put a reference to a FPGA manager: | |
42 | ----------------------------------------- | |
43 | ||
44 | struct fpga_manager *of_fpga_mgr_get(struct device_node *node); | |
9dce0287 AT |
45 | struct fpga_manager *fpga_mgr_get(struct device *dev); |
46 | ||
47 | Given a DT node or device, get an exclusive reference to a FPGA manager. | |
e8f5fda1 AT |
48 | |
49 | void fpga_mgr_put(struct fpga_manager *mgr); | |
50 | ||
9dce0287 | 51 | Release the reference. |
e8f5fda1 AT |
52 | |
53 | ||
54 | To register or unregister the low level FPGA-specific driver: | |
55 | ------------------------------------------------------------- | |
56 | ||
57 | int fpga_mgr_register(struct device *dev, const char *name, | |
58 | const struct fpga_manager_ops *mops, | |
59 | void *priv); | |
60 | ||
61 | void fpga_mgr_unregister(struct device *dev); | |
62 | ||
63 | Use of these two functions is described below in "How To Support a new FPGA | |
64 | device." | |
65 | ||
66 | ||
67 | How to write an image buffer to a supported FPGA | |
68 | ================================================ | |
69 | /* Include to get the API */ | |
70 | #include <linux/fpga/fpga-mgr.h> | |
71 | ||
72 | /* device node that specifies the FPGA manager to use */ | |
73 | struct device_node *mgr_node = ... | |
74 | ||
75 | /* FPGA image is in this buffer. count is size of the buffer. */ | |
76 | char *buf = ... | |
77 | int count = ... | |
78 | ||
40e83578 AT |
79 | /* struct with information about the FPGA image to program. */ |
80 | struct fpga_image_info info; | |
81 | ||
e8f5fda1 | 82 | /* flags indicates whether to do full or partial reconfiguration */ |
40e83578 | 83 | info.flags = 0; |
e8f5fda1 AT |
84 | |
85 | int ret; | |
86 | ||
87 | /* Get exclusive control of FPGA manager */ | |
88 | struct fpga_manager *mgr = of_fpga_mgr_get(mgr_node); | |
89 | ||
90 | /* Load the buffer to the FPGA */ | |
40e83578 | 91 | ret = fpga_mgr_buf_load(mgr, &info, buf, count); |
e8f5fda1 AT |
92 | |
93 | /* Release the FPGA manager */ | |
94 | fpga_mgr_put(mgr); | |
95 | ||
96 | ||
97 | How to write an image file to a supported FPGA | |
98 | ============================================== | |
99 | /* Include to get the API */ | |
100 | #include <linux/fpga/fpga-mgr.h> | |
101 | ||
102 | /* device node that specifies the FPGA manager to use */ | |
103 | struct device_node *mgr_node = ... | |
104 | ||
105 | /* FPGA image is in this file which is in the firmware search path */ | |
106 | const char *path = "fpga-image-9.rbf" | |
107 | ||
40e83578 AT |
108 | /* struct with information about the FPGA image to program. */ |
109 | struct fpga_image_info info; | |
110 | ||
e8f5fda1 | 111 | /* flags indicates whether to do full or partial reconfiguration */ |
40e83578 | 112 | info.flags = 0; |
e8f5fda1 AT |
113 | |
114 | int ret; | |
115 | ||
116 | /* Get exclusive control of FPGA manager */ | |
117 | struct fpga_manager *mgr = of_fpga_mgr_get(mgr_node); | |
118 | ||
119 | /* Get the firmware image (path) and load it to the FPGA */ | |
40e83578 | 120 | ret = fpga_mgr_firmware_load(mgr, &info, path); |
e8f5fda1 AT |
121 | |
122 | /* Release the FPGA manager */ | |
123 | fpga_mgr_put(mgr); | |
124 | ||
125 | ||
126 | How to support a new FPGA device | |
127 | ================================ | |
128 | To add another FPGA manager, write a driver that implements a set of ops. The | |
129 | probe function calls fpga_mgr_register(), such as: | |
130 | ||
131 | static const struct fpga_manager_ops socfpga_fpga_ops = { | |
132 | .write_init = socfpga_fpga_ops_configure_init, | |
133 | .write = socfpga_fpga_ops_configure_write, | |
134 | .write_complete = socfpga_fpga_ops_configure_complete, | |
135 | .state = socfpga_fpga_ops_state, | |
136 | }; | |
137 | ||
138 | static int socfpga_fpga_probe(struct platform_device *pdev) | |
139 | { | |
140 | struct device *dev = &pdev->dev; | |
141 | struct socfpga_fpga_priv *priv; | |
142 | int ret; | |
143 | ||
144 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | |
145 | if (!priv) | |
146 | return -ENOMEM; | |
147 | ||
148 | /* ... do ioremaps, get interrupts, etc. and save | |
149 | them in priv... */ | |
150 | ||
151 | return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager", | |
152 | &socfpga_fpga_ops, priv); | |
153 | } | |
154 | ||
155 | static int socfpga_fpga_remove(struct platform_device *pdev) | |
156 | { | |
157 | fpga_mgr_unregister(&pdev->dev); | |
158 | ||
159 | return 0; | |
160 | } | |
161 | ||
162 | ||
163 | The ops will implement whatever device specific register writes are needed to | |
164 | do the programming sequence for this particular FPGA. These ops return 0 for | |
165 | success or negative error codes otherwise. | |
166 | ||
167 | The programming sequence is: | |
168 | 1. .write_init | |
169 | 2. .write (may be called once or multiple times) | |
170 | 3. .write_complete | |
171 | ||
1d7f1589 JG |
172 | The .write_init function will prepare the FPGA to receive the image data. The |
173 | buffer passed into .write_init will be atmost .initial_header_size bytes long, | |
174 | if the whole bitstream is not immediately available then the core code will | |
175 | buffer up at least this much before starting. | |
e8f5fda1 AT |
176 | |
177 | The .write function writes a buffer to the FPGA. The buffer may be contain the | |
178 | whole FPGA image or may be a smaller chunk of an FPGA image. In the latter | |
179 | case, this function is called multiple times for successive chunks. | |
180 | ||
181 | The .write_complete function is called after all the image has been written | |
182 | to put the FPGA into operating mode. | |
183 | ||
184 | The ops include a .state function which will read the hardware FPGA manager and | |
185 | return a code of type enum fpga_mgr_states. It doesn't result in a change in | |
186 | hardware state. |