Commit | Line | Data |
---|---|---|
5f8d4a90 IB |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Microchip Polarfire FPGA programming over slave SPI interface. | |
4 | */ | |
5 | ||
6 | #include <asm/unaligned.h> | |
7 | #include <linux/delay.h> | |
8 | #include <linux/fpga/fpga-mgr.h> | |
9 | #include <linux/module.h> | |
10 | #include <linux/of_device.h> | |
11 | #include <linux/spi/spi.h> | |
12 | ||
13 | #define MPF_SPI_ISC_ENABLE 0x0B | |
14 | #define MPF_SPI_ISC_DISABLE 0x0C | |
15 | #define MPF_SPI_READ_STATUS 0x00 | |
16 | #define MPF_SPI_READ_DATA 0x01 | |
17 | #define MPF_SPI_FRAME_INIT 0xAE | |
18 | #define MPF_SPI_FRAME 0xEE | |
19 | #define MPF_SPI_PRG_MODE 0x01 | |
20 | #define MPF_SPI_RELEASE 0x23 | |
21 | ||
22 | #define MPF_SPI_FRAME_SIZE 16 | |
23 | ||
24 | #define MPF_HEADER_SIZE_OFFSET 24 | |
25 | #define MPF_DATA_SIZE_OFFSET 55 | |
26 | ||
27 | #define MPF_LOOKUP_TABLE_RECORD_SIZE 9 | |
28 | #define MPF_LOOKUP_TABLE_BLOCK_ID_OFFSET 0 | |
29 | #define MPF_LOOKUP_TABLE_BLOCK_START_OFFSET 1 | |
30 | ||
31 | #define MPF_COMPONENTS_SIZE_ID 5 | |
32 | #define MPF_BITSTREAM_ID 8 | |
33 | ||
34 | #define MPF_BITS_PER_COMPONENT_SIZE 22 | |
35 | ||
36 | #define MPF_STATUS_POLL_RETRIES 10000 | |
37 | #define MPF_STATUS_BUSY BIT(0) | |
38 | #define MPF_STATUS_READY BIT(1) | |
39 | #define MPF_STATUS_SPI_VIOLATION BIT(2) | |
40 | #define MPF_STATUS_SPI_ERROR BIT(3) | |
41 | ||
42 | struct mpf_priv { | |
43 | struct spi_device *spi; | |
44 | bool program_mode; | |
45 | }; | |
46 | ||
47 | static int mpf_read_status(struct spi_device *spi) | |
48 | { | |
49 | u8 status = 0, status_command = MPF_SPI_READ_STATUS; | |
50 | struct spi_transfer xfers[2] = { 0 }; | |
51 | int ret; | |
52 | ||
53 | /* | |
54 | * HW status is returned on MISO in the first byte after CS went | |
55 | * active. However, first reading can be inadequate, so we submit | |
56 | * two identical SPI transfers and use result of the later one. | |
57 | */ | |
58 | xfers[0].tx_buf = &status_command; | |
59 | xfers[1].tx_buf = &status_command; | |
60 | xfers[0].rx_buf = &status; | |
61 | xfers[1].rx_buf = &status; | |
62 | xfers[0].len = 1; | |
63 | xfers[1].len = 1; | |
64 | xfers[0].cs_change = 1; | |
65 | ||
66 | ret = spi_sync_transfer(spi, xfers, 2); | |
67 | ||
68 | if ((status & MPF_STATUS_SPI_VIOLATION) || | |
69 | (status & MPF_STATUS_SPI_ERROR)) | |
70 | ret = -EIO; | |
71 | ||
72 | return ret ? : status; | |
73 | } | |
74 | ||
75 | static enum fpga_mgr_states mpf_ops_state(struct fpga_manager *mgr) | |
76 | { | |
77 | struct mpf_priv *priv = mgr->priv; | |
78 | struct spi_device *spi; | |
79 | bool program_mode; | |
80 | int status; | |
81 | ||
82 | spi = priv->spi; | |
83 | program_mode = priv->program_mode; | |
84 | status = mpf_read_status(spi); | |
85 | ||
86 | if (!program_mode && !status) | |
87 | return FPGA_MGR_STATE_OPERATING; | |
88 | ||
89 | return FPGA_MGR_STATE_UNKNOWN; | |
90 | } | |
91 | ||
92 | static int mpf_ops_parse_header(struct fpga_manager *mgr, | |
93 | struct fpga_image_info *info, | |
94 | const char *buf, size_t count) | |
95 | { | |
96 | size_t component_size_byte_num, component_size_byte_off, | |
97 | components_size_start, bitstream_start, | |
98 | block_id_offset, block_start_offset; | |
99 | u8 header_size, blocks_num, block_id; | |
100 | u32 block_start, component_size; | |
101 | u16 components_num, i; | |
102 | ||
103 | if (!buf) { | |
104 | dev_err(&mgr->dev, "Image buffer is not provided\n"); | |
105 | return -EINVAL; | |
106 | } | |
107 | ||
108 | header_size = *(buf + MPF_HEADER_SIZE_OFFSET); | |
109 | if (header_size > count) { | |
110 | info->header_size = header_size; | |
111 | return -EAGAIN; | |
112 | } | |
113 | ||
114 | /* | |
115 | * Go through look-up table to find out where actual bitstream starts | |
116 | * and where sizes of components of the bitstream lies. | |
117 | */ | |
118 | blocks_num = *(buf + header_size - 1); | |
119 | block_id_offset = header_size + MPF_LOOKUP_TABLE_BLOCK_ID_OFFSET; | |
120 | block_start_offset = header_size + MPF_LOOKUP_TABLE_BLOCK_START_OFFSET; | |
121 | ||
122 | header_size += blocks_num * MPF_LOOKUP_TABLE_RECORD_SIZE; | |
123 | if (header_size > count) { | |
124 | info->header_size = header_size; | |
125 | return -EAGAIN; | |
126 | } | |
127 | ||
128 | components_size_start = 0; | |
129 | bitstream_start = 0; | |
130 | ||
131 | while (blocks_num--) { | |
132 | block_id = *(buf + block_id_offset); | |
133 | block_start = get_unaligned_le32(buf + block_start_offset); | |
134 | ||
135 | switch (block_id) { | |
136 | case MPF_BITSTREAM_ID: | |
137 | bitstream_start = block_start; | |
138 | info->header_size = block_start; | |
139 | if (block_start > count) | |
140 | return -EAGAIN; | |
141 | ||
142 | break; | |
143 | case MPF_COMPONENTS_SIZE_ID: | |
144 | components_size_start = block_start; | |
145 | break; | |
146 | default: | |
147 | break; | |
148 | } | |
149 | ||
150 | if (bitstream_start && components_size_start) | |
151 | break; | |
152 | ||
153 | block_id_offset += MPF_LOOKUP_TABLE_RECORD_SIZE; | |
154 | block_start_offset += MPF_LOOKUP_TABLE_RECORD_SIZE; | |
155 | } | |
156 | ||
157 | if (!bitstream_start || !components_size_start) { | |
158 | dev_err(&mgr->dev, "Failed to parse header look-up table\n"); | |
159 | return -EFAULT; | |
160 | } | |
161 | ||
162 | /* | |
163 | * Parse bitstream size. | |
164 | * Sizes of components of the bitstream are 22-bits long placed next | |
165 | * to each other. Image header should be extended by now up to where | |
166 | * actual bitstream starts, so no need for overflow check anymore. | |
167 | */ | |
168 | components_num = get_unaligned_le16(buf + MPF_DATA_SIZE_OFFSET); | |
169 | ||
170 | for (i = 0; i < components_num; i++) { | |
171 | component_size_byte_num = | |
172 | (i * MPF_BITS_PER_COMPONENT_SIZE) / BITS_PER_BYTE; | |
173 | component_size_byte_off = | |
174 | (i * MPF_BITS_PER_COMPONENT_SIZE) % BITS_PER_BYTE; | |
175 | ||
176 | component_size = get_unaligned_le32(buf + | |
177 | components_size_start + | |
178 | component_size_byte_num); | |
179 | component_size >>= component_size_byte_off; | |
180 | component_size &= GENMASK(MPF_BITS_PER_COMPONENT_SIZE - 1, 0); | |
181 | ||
182 | info->data_size += component_size * MPF_SPI_FRAME_SIZE; | |
183 | } | |
184 | ||
185 | return 0; | |
186 | } | |
187 | ||
188 | /* Poll HW status until busy bit is cleared and mask bits are set. */ | |
189 | static int mpf_poll_status(struct spi_device *spi, u8 mask) | |
190 | { | |
191 | int status, retries = MPF_STATUS_POLL_RETRIES; | |
192 | ||
193 | while (retries--) { | |
194 | status = mpf_read_status(spi); | |
195 | if (status < 0) | |
196 | return status; | |
197 | ||
198 | if (status & MPF_STATUS_BUSY) | |
199 | continue; | |
200 | ||
201 | if (!mask || (status & mask)) | |
202 | return status; | |
203 | } | |
204 | ||
205 | return -EBUSY; | |
206 | } | |
207 | ||
208 | static int mpf_spi_write(struct spi_device *spi, const void *buf, size_t buf_size) | |
209 | { | |
210 | int status = mpf_poll_status(spi, 0); | |
211 | ||
212 | if (status < 0) | |
213 | return status; | |
214 | ||
215 | return spi_write(spi, buf, buf_size); | |
216 | } | |
217 | ||
218 | static int mpf_spi_write_then_read(struct spi_device *spi, | |
219 | const void *txbuf, size_t txbuf_size, | |
220 | void *rxbuf, size_t rxbuf_size) | |
221 | { | |
222 | const u8 read_command[] = { MPF_SPI_READ_DATA }; | |
223 | int ret; | |
224 | ||
225 | ret = mpf_spi_write(spi, txbuf, txbuf_size); | |
226 | if (ret) | |
227 | return ret; | |
228 | ||
229 | ret = mpf_poll_status(spi, MPF_STATUS_READY); | |
230 | if (ret < 0) | |
231 | return ret; | |
232 | ||
233 | return spi_write_then_read(spi, read_command, sizeof(read_command), | |
234 | rxbuf, rxbuf_size); | |
235 | } | |
236 | ||
237 | static int mpf_ops_write_init(struct fpga_manager *mgr, | |
238 | struct fpga_image_info *info, const char *buf, | |
239 | size_t count) | |
240 | { | |
241 | const u8 program_mode[] = { MPF_SPI_FRAME_INIT, MPF_SPI_PRG_MODE }; | |
242 | const u8 isc_en_command[] = { MPF_SPI_ISC_ENABLE }; | |
243 | struct mpf_priv *priv = mgr->priv; | |
244 | struct device *dev = &mgr->dev; | |
245 | struct spi_device *spi; | |
246 | u32 isc_ret = 0; | |
247 | int ret; | |
248 | ||
249 | if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) { | |
250 | dev_err(dev, "Partial reconfiguration is not supported\n"); | |
251 | return -EOPNOTSUPP; | |
252 | } | |
253 | ||
254 | spi = priv->spi; | |
255 | ||
256 | ret = mpf_spi_write_then_read(spi, isc_en_command, sizeof(isc_en_command), | |
257 | &isc_ret, sizeof(isc_ret)); | |
258 | if (ret || isc_ret) { | |
259 | dev_err(dev, "Failed to enable ISC: spi_ret %d, isc_ret %u\n", | |
260 | ret, isc_ret); | |
261 | return -EFAULT; | |
262 | } | |
263 | ||
264 | ret = mpf_spi_write(spi, program_mode, sizeof(program_mode)); | |
265 | if (ret) { | |
266 | dev_err(dev, "Failed to enter program mode: %d\n", ret); | |
267 | return ret; | |
268 | } | |
269 | ||
270 | priv->program_mode = true; | |
271 | ||
272 | return 0; | |
273 | } | |
274 | ||
275 | static int mpf_ops_write(struct fpga_manager *mgr, const char *buf, size_t count) | |
276 | { | |
277 | u8 spi_frame_command[] = { MPF_SPI_FRAME }; | |
278 | struct spi_transfer xfers[2] = { 0 }; | |
279 | struct mpf_priv *priv = mgr->priv; | |
280 | struct device *dev = &mgr->dev; | |
281 | struct spi_device *spi; | |
282 | int ret, i; | |
283 | ||
284 | if (count % MPF_SPI_FRAME_SIZE) { | |
285 | dev_err(dev, "Bitstream size is not a multiple of %d\n", | |
286 | MPF_SPI_FRAME_SIZE); | |
287 | return -EINVAL; | |
288 | } | |
289 | ||
290 | spi = priv->spi; | |
291 | ||
292 | xfers[0].tx_buf = spi_frame_command; | |
293 | xfers[0].len = sizeof(spi_frame_command); | |
294 | ||
295 | for (i = 0; i < count / MPF_SPI_FRAME_SIZE; i++) { | |
296 | xfers[1].tx_buf = buf + i * MPF_SPI_FRAME_SIZE; | |
297 | xfers[1].len = MPF_SPI_FRAME_SIZE; | |
298 | ||
299 | ret = mpf_poll_status(spi, 0); | |
300 | if (ret >= 0) | |
301 | ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); | |
302 | ||
303 | if (ret) { | |
304 | dev_err(dev, "Failed to write bitstream frame %d/%zu\n", | |
305 | i, count / MPF_SPI_FRAME_SIZE); | |
306 | return ret; | |
307 | } | |
308 | } | |
309 | ||
310 | return 0; | |
311 | } | |
312 | ||
313 | static int mpf_ops_write_complete(struct fpga_manager *mgr, | |
314 | struct fpga_image_info *info) | |
315 | { | |
316 | const u8 isc_dis_command[] = { MPF_SPI_ISC_DISABLE }; | |
317 | const u8 release_command[] = { MPF_SPI_RELEASE }; | |
318 | struct mpf_priv *priv = mgr->priv; | |
319 | struct device *dev = &mgr->dev; | |
320 | struct spi_device *spi; | |
321 | int ret; | |
322 | ||
323 | spi = priv->spi; | |
324 | ||
325 | ret = mpf_spi_write(spi, isc_dis_command, sizeof(isc_dis_command)); | |
326 | if (ret) { | |
327 | dev_err(dev, "Failed to disable ISC: %d\n", ret); | |
328 | return ret; | |
329 | } | |
330 | ||
331 | usleep_range(1000, 2000); | |
332 | ||
333 | ret = mpf_spi_write(spi, release_command, sizeof(release_command)); | |
334 | if (ret) { | |
335 | dev_err(dev, "Failed to exit program mode: %d\n", ret); | |
336 | return ret; | |
337 | } | |
338 | ||
339 | priv->program_mode = false; | |
340 | ||
341 | return 0; | |
342 | } | |
343 | ||
344 | static const struct fpga_manager_ops mpf_ops = { | |
345 | .state = mpf_ops_state, | |
346 | .initial_header_size = 71, | |
347 | .skip_header = true, | |
348 | .parse_header = mpf_ops_parse_header, | |
349 | .write_init = mpf_ops_write_init, | |
350 | .write = mpf_ops_write, | |
351 | .write_complete = mpf_ops_write_complete, | |
352 | }; | |
353 | ||
354 | static int mpf_probe(struct spi_device *spi) | |
355 | { | |
356 | struct device *dev = &spi->dev; | |
357 | struct fpga_manager *mgr; | |
358 | struct mpf_priv *priv; | |
359 | ||
360 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | |
361 | if (!priv) | |
362 | return -ENOMEM; | |
363 | ||
364 | priv->spi = spi; | |
365 | ||
366 | mgr = devm_fpga_mgr_register(dev, "Microchip Polarfire SPI FPGA Manager", | |
367 | &mpf_ops, priv); | |
368 | ||
369 | return PTR_ERR_OR_ZERO(mgr); | |
370 | } | |
371 | ||
372 | static const struct spi_device_id mpf_spi_ids[] = { | |
373 | { .name = "mpf-spi-fpga-mgr", }, | |
374 | {}, | |
375 | }; | |
376 | MODULE_DEVICE_TABLE(spi, mpf_spi_ids); | |
377 | ||
378 | #if IS_ENABLED(CONFIG_OF) | |
379 | static const struct of_device_id mpf_of_ids[] = { | |
380 | { .compatible = "microchip,mpf-spi-fpga-mgr" }, | |
381 | {}, | |
382 | }; | |
383 | MODULE_DEVICE_TABLE(of, mpf_of_ids); | |
384 | #endif /* IS_ENABLED(CONFIG_OF) */ | |
385 | ||
386 | static struct spi_driver mpf_driver = { | |
387 | .probe = mpf_probe, | |
388 | .id_table = mpf_spi_ids, | |
389 | .driver = { | |
390 | .name = "microchip_mpf_spi_fpga_mgr", | |
391 | .of_match_table = of_match_ptr(mpf_of_ids), | |
392 | }, | |
393 | }; | |
394 | ||
395 | module_spi_driver(mpf_driver); | |
396 | ||
397 | MODULE_DESCRIPTION("Microchip Polarfire SPI FPGA Manager"); | |
398 | MODULE_LICENSE("GPL"); |