summaryrefslogtreecommitdiffstats
path: root/drivers/fpga
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/fpga')
-rw-r--r--drivers/fpga/Kconfig7
-rw-r--r--drivers/fpga/Makefile1
-rw-r--r--drivers/fpga/machxo2-spi.c403
3 files changed, 411 insertions, 0 deletions
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index fd539132542e..ee9c5420c47f 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -69,6 +69,13 @@ config FPGA_MGR_ICE40_SPI
69 help 69 help
70 FPGA manager driver support for Lattice iCE40 FPGAs over SPI. 70 FPGA manager driver support for Lattice iCE40 FPGAs over SPI.
71 71
72config FPGA_MGR_MACHXO2_SPI
73 tristate "Lattice MachXO2 SPI"
74 depends on SPI
75 help
76 FPGA manager driver support for Lattice MachXO2 configuration
77 over slave SPI interface.
78
72config FPGA_MGR_TS73XX 79config FPGA_MGR_TS73XX
73 tristate "Technologic Systems TS-73xx SBC FPGA Manager" 80 tristate "Technologic Systems TS-73xx SBC FPGA Manager"
74 depends on ARCH_EP93XX && MACH_TS72XX 81 depends on ARCH_EP93XX && MACH_TS72XX
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 3cb276a0f88d..f9803dad6919 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o
10obj-$(CONFIG_FPGA_MGR_ALTERA_CVP) += altera-cvp.o 10obj-$(CONFIG_FPGA_MGR_ALTERA_CVP) += altera-cvp.o
11obj-$(CONFIG_FPGA_MGR_ALTERA_PS_SPI) += altera-ps-spi.o 11obj-$(CONFIG_FPGA_MGR_ALTERA_PS_SPI) += altera-ps-spi.o
12obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o 12obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o
13obj-$(CONFIG_FPGA_MGR_MACHXO2_SPI) += machxo2-spi.o
13obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o 14obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
14obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o 15obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
15obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o 16obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o
diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c
new file mode 100644
index 000000000000..8e95ec9c5c9a
--- /dev/null
+++ b/drivers/fpga/machxo2-spi.c
@@ -0,0 +1,403 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Lattice MachXO2 Slave SPI Driver
4 *
5 * Manage Lattice FPGA firmware that is loaded over SPI using
6 * the slave serial configuration interface.
7 *
8 * Copyright (C) 2018 Paolo Pisati <p.pisati@gmail.com>
9 */
10
11#include <linux/delay.h>
12#include <linux/fpga/fpga-mgr.h>
13#include <linux/gpio/consumer.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/spi/spi.h>
17
18/* MachXO2 Programming Guide - sysCONFIG Programming Commands */
19#define IDCODE_PUB {0xe0, 0x00, 0x00, 0x00}
20#define ISC_ENABLE {0xc6, 0x08, 0x00, 0x00}
21#define ISC_ERASE {0x0e, 0x04, 0x00, 0x00}
22#define ISC_PROGRAMDONE {0x5e, 0x00, 0x00, 0x00}
23#define LSC_INITADDRESS {0x46, 0x00, 0x00, 0x00}
24#define LSC_PROGINCRNV {0x70, 0x00, 0x00, 0x01}
25#define LSC_READ_STATUS {0x3c, 0x00, 0x00, 0x00}
26#define LSC_REFRESH {0x79, 0x00, 0x00, 0x00}
27
28/*
29 * Max CCLK in Slave SPI mode according to 'MachXO2 Family Data
30 * Sheet' sysCONFIG Port Timing Specifications (3-36)
31 */
32#define MACHXO2_MAX_SPEED 66000000
33
34#define MACHXO2_LOW_DELAY_USEC 5
35#define MACHXO2_HIGH_DELAY_USEC 200
36#define MACHXO2_REFRESH_USEC 4800
37#define MACHXO2_MAX_BUSY_LOOP 128
38#define MACHXO2_MAX_REFRESH_LOOP 16
39
40#define MACHXO2_PAGE_SIZE 16
41#define MACHXO2_BUF_SIZE (MACHXO2_PAGE_SIZE + 4)
42
43/* Status register bits, errors and error mask */
44#define BUSY 12
45#define DONE 8
46#define DVER 27
47#define ENAB 9
48#define ERRBITS 23
49#define ERRMASK 7
50#define FAIL 13
51
52#define ENOERR 0 /* no error */
53#define EID 1
54#define ECMD 2
55#define ECRC 3
56#define EPREAM 4 /* preamble error */
57#define EABRT 5 /* abort error */
58#define EOVERFL 6 /* overflow error */
59#define ESDMEOF 7 /* SDM EOF */
60
61static inline u8 get_err(unsigned long *status)
62{
63 return (*status >> ERRBITS) & ERRMASK;
64}
65
66static int get_status(struct spi_device *spi, unsigned long *status)
67{
68 struct spi_message msg;
69 struct spi_transfer rx, tx;
70 static const u8 cmd[] = LSC_READ_STATUS;
71 int ret;
72
73 memset(&rx, 0, sizeof(rx));
74 memset(&tx, 0, sizeof(tx));
75 tx.tx_buf = cmd;
76 tx.len = sizeof(cmd);
77 rx.rx_buf = status;
78 rx.len = 4;
79 spi_message_init(&msg);
80 spi_message_add_tail(&tx, &msg);
81 spi_message_add_tail(&rx, &msg);
82 ret = spi_sync(spi, &msg);
83 if (ret)
84 return ret;
85
86 *status = be32_to_cpu(*status);
87
88 return 0;
89}
90
91#ifdef DEBUG
92static const char *get_err_string(u8 err)
93{
94 switch (err) {
95 case ENOERR: return "No Error";
96 case EID: return "ID ERR";
97 case ECMD: return "CMD ERR";
98 case ECRC: return "CRC ERR";
99 case EPREAM: return "Preamble ERR";
100 case EABRT: return "Abort ERR";
101 case EOVERFL: return "Overflow ERR";
102 case ESDMEOF: return "SDM EOF";
103 }
104
105 return "Default switch case";
106}
107#endif
108
109static void dump_status_reg(unsigned long *status)
110{
111#ifdef DEBUG
112 pr_debug("machxo2 status: 0x%08lX - done=%d, cfgena=%d, busy=%d, fail=%d, devver=%d, err=%s\n",
113 *status, test_bit(DONE, status), test_bit(ENAB, status),
114 test_bit(BUSY, status), test_bit(FAIL, status),
115 test_bit(DVER, status), get_err_string(get_err(status)));
116#endif
117}
118
119static int wait_until_not_busy(struct spi_device *spi)
120{
121 unsigned long status;
122 int ret, loop = 0;
123
124 do {
125 ret = get_status(spi, &status);
126 if (ret)
127 return ret;
128 if (++loop >= MACHXO2_MAX_BUSY_LOOP)
129 return -EBUSY;
130 } while (test_bit(BUSY, &status));
131
132 return 0;
133}
134
135static int machxo2_cleanup(struct fpga_manager *mgr)
136{
137 struct spi_device *spi = mgr->priv;
138 struct spi_message msg;
139 struct spi_transfer tx[2];
140 static const u8 erase[] = ISC_ERASE;
141 static const u8 refresh[] = LSC_REFRESH;
142 int ret;
143
144 memset(tx, 0, sizeof(tx));
145 spi_message_init(&msg);
146 tx[0].tx_buf = &erase;
147 tx[0].len = sizeof(erase);
148 spi_message_add_tail(&tx[0], &msg);
149 ret = spi_sync(spi, &msg);
150 if (ret)
151 goto fail;
152
153 ret = wait_until_not_busy(spi);
154 if (ret)
155 goto fail;
156
157 spi_message_init(&msg);
158 tx[1].tx_buf = &refresh;
159 tx[1].len = sizeof(refresh);
160 tx[1].delay_usecs = MACHXO2_REFRESH_USEC;
161 spi_message_add_tail(&tx[1], &msg);
162 ret = spi_sync(spi, &msg);
163 if (ret)
164 goto fail;
165
166 return 0;
167fail:
168 dev_err(&mgr->dev, "Cleanup failed\n");
169
170 return ret;
171}
172
173static enum fpga_mgr_states machxo2_spi_state(struct fpga_manager *mgr)
174{
175 struct spi_device *spi = mgr->priv;
176 unsigned long status;
177
178 get_status(spi, &status);
179 if (!test_bit(BUSY, &status) && test_bit(DONE, &status) &&
180 get_err(&status) == ENOERR)
181 return FPGA_MGR_STATE_OPERATING;
182
183 return FPGA_MGR_STATE_UNKNOWN;
184}
185
186static int machxo2_write_init(struct fpga_manager *mgr,
187 struct fpga_image_info *info,
188 const char *buf, size_t count)
189{
190 struct spi_device *spi = mgr->priv;
191 struct spi_message msg;
192 struct spi_transfer tx[3];
193 static const u8 enable[] = ISC_ENABLE;
194 static const u8 erase[] = ISC_ERASE;
195 static const u8 initaddr[] = LSC_INITADDRESS;
196 unsigned long status;
197 int ret;
198
199 if ((info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
200 dev_err(&mgr->dev,
201 "Partial reconfiguration is not supported\n");
202 return -ENOTSUPP;
203 }
204
205 get_status(spi, &status);
206 dump_status_reg(&status);
207 memset(tx, 0, sizeof(tx));
208 spi_message_init(&msg);
209 tx[0].tx_buf = &enable;
210 tx[0].len = sizeof(enable);
211 tx[0].delay_usecs = MACHXO2_LOW_DELAY_USEC;
212 spi_message_add_tail(&tx[0], &msg);
213
214 tx[1].tx_buf = &erase;
215 tx[1].len = sizeof(erase);
216 spi_message_add_tail(&tx[1], &msg);
217 ret = spi_sync(spi, &msg);
218 if (ret)
219 goto fail;
220
221 ret = wait_until_not_busy(spi);
222 if (ret)
223 goto fail;
224
225 get_status(spi, &status);
226 if (test_bit(FAIL, &status))
227 goto fail;
228 dump_status_reg(&status);
229
230 spi_message_init(&msg);
231 tx[2].tx_buf = &initaddr;
232 tx[2].len = sizeof(initaddr);
233 spi_message_add_tail(&tx[2], &msg);
234 ret = spi_sync(spi, &msg);
235 if (ret)
236 goto fail;
237
238 get_status(spi, &status);
239 dump_status_reg(&status);
240
241 return 0;
242fail:
243 dev_err(&mgr->dev, "Error during FPGA init.\n");
244
245 return ret;
246}
247
248static int machxo2_write(struct fpga_manager *mgr, const char *buf,
249 size_t count)
250{
251 struct spi_device *spi = mgr->priv;
252 struct spi_message msg;
253 struct spi_transfer tx;
254 static const u8 progincr[] = LSC_PROGINCRNV;
255 u8 payload[MACHXO2_BUF_SIZE];
256 unsigned long status;
257 int i, ret;
258
259 if (count % MACHXO2_PAGE_SIZE != 0) {
260 dev_err(&mgr->dev, "Malformed payload.\n");
261 return -EINVAL;
262 }
263 get_status(spi, &status);
264 dump_status_reg(&status);
265 memcpy(payload, &progincr, sizeof(progincr));
266 for (i = 0; i < count; i += MACHXO2_PAGE_SIZE) {
267 memcpy(&payload[sizeof(progincr)], &buf[i], MACHXO2_PAGE_SIZE);
268 memset(&tx, 0, sizeof(tx));
269 spi_message_init(&msg);
270 tx.tx_buf = payload;
271 tx.len = MACHXO2_BUF_SIZE;
272 tx.delay_usecs = MACHXO2_HIGH_DELAY_USEC;
273 spi_message_add_tail(&tx, &msg);
274 ret = spi_sync(spi, &msg);
275 if (ret) {
276 dev_err(&mgr->dev, "Error loading the bitstream.\n");
277 return ret;
278 }
279 }
280 get_status(spi, &status);
281 dump_status_reg(&status);
282
283 return 0;
284}
285
286static int machxo2_write_complete(struct fpga_manager *mgr,
287 struct fpga_image_info *info)
288{
289 struct spi_device *spi = mgr->priv;
290 struct spi_message msg;
291 struct spi_transfer tx[2];
292 static const u8 progdone[] = ISC_PROGRAMDONE;
293 static const u8 refresh[] = LSC_REFRESH;
294 unsigned long status;
295 int ret, refreshloop = 0;
296
297 memset(tx, 0, sizeof(tx));
298 spi_message_init(&msg);
299 tx[0].tx_buf = &progdone;
300 tx[0].len = sizeof(progdone);
301 spi_message_add_tail(&tx[0], &msg);
302 ret = spi_sync(spi, &msg);
303 if (ret)
304 goto fail;
305 ret = wait_until_not_busy(spi);
306 if (ret)
307 goto fail;
308
309 get_status(spi, &status);
310 dump_status_reg(&status);
311 if (!test_bit(DONE, &status)) {
312 machxo2_cleanup(mgr);
313 goto fail;
314 }
315
316 do {
317 spi_message_init(&msg);
318 tx[1].tx_buf = &refresh;
319 tx[1].len = sizeof(refresh);
320 tx[1].delay_usecs = MACHXO2_REFRESH_USEC;
321 spi_message_add_tail(&tx[1], &msg);
322 ret = spi_sync(spi, &msg);
323 if (ret)
324 goto fail;
325
326 /* check refresh status */
327 get_status(spi, &status);
328 dump_status_reg(&status);
329 if (!test_bit(BUSY, &status) && test_bit(DONE, &status) &&
330 get_err(&status) == ENOERR)
331 break;
332 if (++refreshloop == MACHXO2_MAX_REFRESH_LOOP) {
333 machxo2_cleanup(mgr);
334 goto fail;
335 }
336 } while (1);
337
338 get_status(spi, &status);
339 dump_status_reg(&status);
340
341 return 0;
342fail:
343 dev_err(&mgr->dev, "Refresh failed.\n");
344
345 return ret;
346}
347
348static const struct fpga_manager_ops machxo2_ops = {
349 .state = machxo2_spi_state,
350 .write_init = machxo2_write_init,
351 .write = machxo2_write,
352 .write_complete = machxo2_write_complete,
353};
354
355static int machxo2_spi_probe(struct spi_device *spi)
356{
357 struct device *dev = &spi->dev;
358
359 if (spi->max_speed_hz > MACHXO2_MAX_SPEED) {
360 dev_err(dev, "Speed is too high\n");
361 return -EINVAL;
362 }
363
364 return fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager",
365 &machxo2_ops, spi);
366}
367
368static int machxo2_spi_remove(struct spi_device *spi)
369{
370 struct device *dev = &spi->dev;
371
372 fpga_mgr_unregister(dev);
373
374 return 0;
375}
376
377static const struct of_device_id of_match[] = {
378 { .compatible = "lattice,machxo2-slave-spi", },
379 {}
380};
381MODULE_DEVICE_TABLE(of, of_match);
382
383static const struct spi_device_id lattice_ids[] = {
384 { "machxo2-slave-spi", 0 },
385 { },
386};
387MODULE_DEVICE_TABLE(spi, lattice_ids);
388
389static struct spi_driver machxo2_spi_driver = {
390 .driver = {
391 .name = "machxo2-slave-spi",
392 .of_match_table = of_match_ptr(of_match),
393 },
394 .probe = machxo2_spi_probe,
395 .remove = machxo2_spi_remove,
396 .id_table = lattice_ids,
397};
398
399module_spi_driver(machxo2_spi_driver)
400
401MODULE_AUTHOR("Paolo Pisati <p.pisati@gmail.com>");
402MODULE_DESCRIPTION("Load Lattice FPGA firmware over SPI");
403MODULE_LICENSE("GPL v2");