1 /*
2 * Copyright (c) 2021-2022 Antmicro <www.antmicro.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT xlnx_fpga
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/fpga.h>
11 #include "fpga_zynqmp.h"
12 #include <errno.h>
13 #include <string.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(fpga_zynqmp);
20
power_up_fpga(void)21 static void power_up_fpga(void)
22 {
23 PMU_GLOBAL_PWRUP_EN = PWR_PL_MASK;
24 PMU_REQ_PWRUP_TRIG = PWR_PL_MASK;
25
26 while (PWR_STATUS & PWR_PL_MASK) {
27 };
28 }
29
30 struct zynqmp_fpga_data {
31 char FPGA_info[16];
32 };
33
update_part_name(const struct device * dev)34 static void update_part_name(const struct device *dev)
35 {
36 struct zynqmp_fpga_data *data = dev->data;
37
38 int zu_number = 0;
39
40 switch (IDCODE & IDCODE_MASK) {
41 case ZU2_IDCODE:
42 zu_number = 2;
43 break;
44 case ZU3_IDCODE:
45 zu_number = 3;
46 break;
47 case ZU4_IDCODE:
48 zu_number = 4;
49 break;
50 case ZU5_IDCODE:
51 zu_number = 5;
52 break;
53 case ZU6_IDCODE:
54 zu_number = 6;
55 break;
56 case ZU7_IDCODE:
57 zu_number = 7;
58 break;
59 case ZU9_IDCODE:
60 zu_number = 9;
61 break;
62 case ZU11_IDCODE:
63 zu_number = 11;
64 break;
65 case ZU15_IDCODE:
66 zu_number = 15;
67 break;
68 case ZU17_IDCODE:
69 zu_number = 17;
70 break;
71 case ZU19_IDCODE:
72 zu_number = 19;
73 break;
74 case ZU21_IDCODE:
75 zu_number = 21;
76 break;
77 case ZU25_IDCODE:
78 zu_number = 25;
79 break;
80 case ZU27_IDCODE:
81 zu_number = 27;
82 break;
83 case ZU28_IDCODE:
84 zu_number = 28;
85 break;
86 case ZU29_IDCODE:
87 zu_number = 29;
88 break;
89 case ZU39_IDCODE:
90 zu_number = 39;
91 break;
92 case ZU43_IDCODE:
93 zu_number = 43;
94 break;
95 case ZU46_IDCODE:
96 zu_number = 46;
97 break;
98 case ZU47_IDCODE:
99 zu_number = 47;
100 break;
101 case ZU48_IDCODE:
102 zu_number = 48;
103 break;
104 case ZU49_IDCODE:
105 zu_number = 49;
106 break;
107 }
108
109 if (zu_number == 0) {
110 snprintf(data->FPGA_info, sizeof(data->FPGA_info), "unknown");
111 } else {
112 snprintf(data->FPGA_info, sizeof(data->FPGA_info), "Part name: ZU%d", zu_number);
113 }
114
115 }
116
117 /*
118 * This function is responsible for shifting the bitstream
119 * by its header and extracting information from this header.
120 * The bitstream header has 5 sections starting with the letters a,b,c...
121 * Each section has the following structure:
122 * [key][length of data][data]
123 */
parse_header(const struct device * dev,uint32_t * image_ptr,uint32_t * img_size)124 static uint32_t *parse_header(const struct device *dev, uint32_t *image_ptr,
125 uint32_t *img_size)
126 {
127 unsigned char *header = (unsigned char *)image_ptr;
128
129 uint32_t length = XLNX_BITSTREAM_SECTION_LENGTH(header);
130
131 /* shift to the next section*/
132 header += 0x4U + length;
133
134 if (*header++ != 'a') {
135 LOG_ERR("Incorrect bitstream format");
136 return NULL;
137 }
138
139 length = XLNX_BITSTREAM_SECTION_LENGTH(header);
140 /* shift to the data section*/
141 header += 0x2U;
142
143 LOG_DBG("Design name = %s", header);
144
145 header += length;
146
147 if (*header++ != 'b') {
148 LOG_ERR("Incorrect bitstream format");
149 return NULL;
150 }
151
152 length = XLNX_BITSTREAM_SECTION_LENGTH(header);
153 /* shift to the data section*/
154 header += 0x2U;
155 LOG_DBG("Part name = %s", header);
156
157 header += length;
158
159 if (*header++ != 'c') {
160 LOG_ERR("Incorrect bitstream format");
161 return NULL;
162 }
163
164 length = XLNX_BITSTREAM_SECTION_LENGTH(header);
165 /* shift to the data section*/
166 header += 0x2U;
167
168 LOG_DBG("Date = %s", header);
169
170 header += length;
171
172 if (*header++ != 'd') {
173 LOG_ERR("Incorrect bitstream format");
174 return NULL;
175 }
176
177 length = XLNX_BITSTREAM_SECTION_LENGTH(header);
178 /* shift to the data section*/
179 header += 0x2U;
180
181 LOG_DBG("Time = %s", header);
182
183 header += length;
184
185 if (*header++ != 'e') {
186 LOG_ERR("Incorrect bitstream format");
187 return NULL;
188 }
189
190 /*
191 * The last section is the raw bitstream.
192 * It is preceded by its size, which is needed for DMA transfer.
193 */
194 *img_size =
195 ((uint32_t)*header << 24) | ((uint32_t) *(header + 1) << 16) |
196 ((uint32_t) *(header + 2) << 8) | ((uint32_t) *(header + 3));
197
198 return (uint32_t *)header;
199 }
200
csudma_transfer(uint32_t size)201 static int csudma_transfer(uint32_t size)
202 {
203 /* setup the source DMA channel */
204 CSUDMA_SRC_ADDR = (uint32_t)BITSTREAM & CSUDMA_SRC_ADDR_MASK;
205 CSUDMA_SRC_ADDR_MSB = 0;
206 CSUDMA_SRC_SIZE = size << CSUDMA_SRC_SIZE_SHIFT;
207
208 /* wait for the SRC_DMA to complete */
209 while ((CSUDMA_SRC_I_STS & CSUDMA_I_STS_DONE_MASK) != CSUDMA_I_STS_DONE_MASK) {
210 };
211
212 /* acknowledge the transfer has completed */
213 CSUDMA_SRC_I_STS = CSUDMA_I_STS_DONE_MASK;
214
215 return 0;
216 }
217
wait_for_done(void)218 static int wait_for_done(void)
219 {
220 /* wait for PCAP PL_DONE */
221 while ((PCAP_STATUS & PCAP_PL_DONE_MASK) != PCAP_PL_DONE_MASK) {
222 };
223
224 PCAP_RESET = PCAP_RESET_MASK;
225 power_up_fpga();
226
227 return 0;
228 }
229
zynqmp_fpga_get_status(const struct device * dev)230 static enum FPGA_status zynqmp_fpga_get_status(const struct device *dev)
231 {
232 ARG_UNUSED(dev);
233
234 if ((PCAP_STATUS & PCAP_PL_INIT_MASK) && (PCAP_STATUS & PCAP_PL_DONE_MASK)) {
235 return FPGA_STATUS_ACTIVE;
236 } else {
237 return FPGA_STATUS_INACTIVE;
238 }
239 }
240
zynqmp_fpga_get_info(const struct device * dev)241 static const char *zynqmp_fpga_get_info(const struct device *dev)
242 {
243 struct zynqmp_fpga_data *data = dev->data;
244
245 return data->FPGA_info;
246 }
247
zynqmp_fpga_reset(const struct device * dev)248 static int zynqmp_fpga_reset(const struct device *dev)
249 {
250 ARG_UNUSED(dev);
251
252 /* Reset PL */
253 PCAP_PROG = PCAP_PROG_RESET_MASK;
254 PCAP_PROG = ~PCAP_PROG_RESET_MASK;
255
256 while ((PCAP_STATUS & PCAP_CFG_RESET) != PCAP_CFG_RESET) {
257 };
258
259 return 0;
260 }
261
init_pcap(const struct device * dev)262 static int init_pcap(const struct device *dev)
263 {
264 /* take PCAP out of Reset */
265 PCAP_RESET = ~PCAP_RESET_MASK;
266
267 /* select PCAP mode and change PCAP to write mode */
268 PCAP_CTRL = PCAP_PR_MASK;
269 PCAP_RDWR = PCAP_WRITE_MASK;
270
271 power_up_fpga();
272
273 /* setup the SSS */
274 CSU_SSS_CFG = PCAP_PCAP_SSS_MASK;
275
276 zynqmp_fpga_reset(dev);
277
278 /* wait for pl init */
279 while ((PCAP_STATUS & PCAP_PL_INIT_MASK) != PCAP_PL_INIT_MASK) {
280 };
281
282 return 0;
283 }
284
zynqmp_fpga_load(const struct device * dev,uint32_t * image_ptr,uint32_t img_size)285 static int zynqmp_fpga_load(const struct device *dev, uint32_t *image_ptr,
286 uint32_t img_size)
287 {
288 uint32_t *addr = parse_header(dev, image_ptr, &img_size);
289
290 if (addr == NULL) {
291 LOG_ERR("Failed to read bitstream");
292 return -EINVAL;
293 }
294
295 for (int i = 0; i < (img_size / 4); i++) {
296 *(BITSTREAM + i) = __bswap_32(*(addr + i));
297 }
298
299 init_pcap(dev);
300 csudma_transfer(img_size);
301 wait_for_done();
302
303 return 0;
304 }
305
zynqmp_fpga_init(const struct device * dev)306 static int zynqmp_fpga_init(const struct device *dev)
307 {
308 /* turn on PCAP CLK */
309 PCAP_CLK_CTRL = PCAP_CLK_CTRL | PCAP_CLKACT_MASK;
310
311 update_part_name(dev);
312
313 return 0;
314 }
315
316 static struct zynqmp_fpga_data fpga_data;
317
318 static const struct fpga_driver_api zynqmp_api = {
319 .reset = zynqmp_fpga_reset,
320 .load = zynqmp_fpga_load,
321 .get_status = zynqmp_fpga_get_status,
322 .get_info = zynqmp_fpga_get_info
323 };
324
325 DEVICE_DT_INST_DEFINE(0, &zynqmp_fpga_init, NULL, &fpga_data, NULL,
326 POST_KERNEL, CONFIG_FPGA_INIT_PRIORITY, &zynqmp_api);
327