Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/fpga/lattice-sysconfig.c
26381 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Lattice FPGA sysCONFIG interface functions independent of port type.
4
*/
5
6
#include <linux/delay.h>
7
#include <linux/fpga/fpga-mgr.h>
8
#include <linux/gpio/consumer.h>
9
#include <linux/iopoll.h>
10
11
#include "lattice-sysconfig.h"
12
13
static int sysconfig_cmd_write(struct sysconfig_priv *priv, const void *buf,
14
size_t buf_len)
15
{
16
return priv->command_transfer(priv, buf, buf_len, NULL, 0);
17
}
18
19
static int sysconfig_cmd_read(struct sysconfig_priv *priv, const void *tx_buf,
20
size_t tx_len, void *rx_buf, size_t rx_len)
21
{
22
return priv->command_transfer(priv, tx_buf, tx_len, rx_buf, rx_len);
23
}
24
25
static int sysconfig_read_busy(struct sysconfig_priv *priv)
26
{
27
const u8 lsc_check_busy[] = SYSCONFIG_LSC_CHECK_BUSY;
28
u8 busy;
29
int ret;
30
31
ret = sysconfig_cmd_read(priv, lsc_check_busy, sizeof(lsc_check_busy),
32
&busy, sizeof(busy));
33
34
return ret ? : busy;
35
}
36
37
static int sysconfig_poll_busy(struct sysconfig_priv *priv)
38
{
39
int ret, busy;
40
41
ret = read_poll_timeout(sysconfig_read_busy, busy, busy <= 0,
42
SYSCONFIG_POLL_INTERVAL_US,
43
SYSCONFIG_POLL_BUSY_TIMEOUT_US, false, priv);
44
45
return ret ? : busy;
46
}
47
48
static int sysconfig_read_status(struct sysconfig_priv *priv, u32 *status)
49
{
50
const u8 lsc_read_status[] = SYSCONFIG_LSC_READ_STATUS;
51
__be32 device_status;
52
int ret;
53
54
ret = sysconfig_cmd_read(priv, lsc_read_status, sizeof(lsc_read_status),
55
&device_status, sizeof(device_status));
56
if (ret)
57
return ret;
58
59
*status = be32_to_cpu(device_status);
60
61
return 0;
62
}
63
64
static int sysconfig_poll_status(struct sysconfig_priv *priv, u32 *status)
65
{
66
int ret = sysconfig_poll_busy(priv);
67
68
if (ret)
69
return ret;
70
71
return sysconfig_read_status(priv, status);
72
}
73
74
static int sysconfig_poll_gpio(struct gpio_desc *gpio, bool is_active)
75
{
76
int ret, val;
77
78
ret = read_poll_timeout(gpiod_get_value, val,
79
val < 0 || !!val == is_active,
80
SYSCONFIG_POLL_INTERVAL_US,
81
SYSCONFIG_POLL_GPIO_TIMEOUT_US, false, gpio);
82
83
if (val < 0)
84
return val;
85
86
return ret;
87
}
88
89
static int sysconfig_gpio_refresh(struct sysconfig_priv *priv)
90
{
91
struct gpio_desc *program = priv->program;
92
struct gpio_desc *init = priv->init;
93
struct gpio_desc *done = priv->done;
94
int ret;
95
96
/* Enter init mode */
97
gpiod_set_value(program, 1);
98
99
ret = sysconfig_poll_gpio(init, true);
100
if (!ret)
101
ret = sysconfig_poll_gpio(done, false);
102
103
if (ret)
104
return ret;
105
106
/* Enter program mode */
107
gpiod_set_value(program, 0);
108
109
return sysconfig_poll_gpio(init, false);
110
}
111
112
static int sysconfig_lsc_refresh(struct sysconfig_priv *priv)
113
{
114
static const u8 lsc_refresh[] = SYSCONFIG_LSC_REFRESH;
115
int ret;
116
117
ret = sysconfig_cmd_write(priv, lsc_refresh, sizeof(lsc_refresh));
118
if (ret)
119
return ret;
120
121
usleep_range(4000, 8000);
122
123
return 0;
124
}
125
126
static int sysconfig_refresh(struct sysconfig_priv *priv)
127
{
128
struct gpio_desc *program = priv->program;
129
struct gpio_desc *init = priv->init;
130
struct gpio_desc *done = priv->done;
131
132
if (program && init && done)
133
return sysconfig_gpio_refresh(priv);
134
135
return sysconfig_lsc_refresh(priv);
136
}
137
138
static int sysconfig_isc_enable(struct sysconfig_priv *priv)
139
{
140
u8 isc_enable[] = SYSCONFIG_ISC_ENABLE;
141
u32 status;
142
int ret;
143
144
ret = sysconfig_cmd_write(priv, isc_enable, sizeof(isc_enable));
145
if (ret)
146
return ret;
147
148
ret = sysconfig_poll_status(priv, &status);
149
if (ret)
150
return ret;
151
152
if (status & SYSCONFIG_STATUS_FAIL)
153
return -EFAULT;
154
155
return 0;
156
}
157
158
static int sysconfig_isc_erase(struct sysconfig_priv *priv)
159
{
160
u8 isc_erase[] = SYSCONFIG_ISC_ERASE;
161
u32 status;
162
int ret;
163
164
ret = sysconfig_cmd_write(priv, isc_erase, sizeof(isc_erase));
165
if (ret)
166
return ret;
167
168
ret = sysconfig_poll_status(priv, &status);
169
if (ret)
170
return ret;
171
172
if (status & SYSCONFIG_STATUS_FAIL)
173
return -EFAULT;
174
175
return 0;
176
}
177
178
static int sysconfig_isc_init(struct sysconfig_priv *priv)
179
{
180
int ret = sysconfig_isc_enable(priv);
181
182
if (ret)
183
return ret;
184
185
return sysconfig_isc_erase(priv);
186
}
187
188
static int sysconfig_lsc_init_addr(struct sysconfig_priv *priv)
189
{
190
const u8 lsc_init_addr[] = SYSCONFIG_LSC_INIT_ADDR;
191
192
return sysconfig_cmd_write(priv, lsc_init_addr, sizeof(lsc_init_addr));
193
}
194
195
static int sysconfig_burst_write_init(struct sysconfig_priv *priv)
196
{
197
return priv->bitstream_burst_write_init(priv);
198
}
199
200
static int sysconfig_burst_write_complete(struct sysconfig_priv *priv)
201
{
202
return priv->bitstream_burst_write_complete(priv);
203
}
204
205
static int sysconfig_bitstream_burst_write(struct sysconfig_priv *priv,
206
const char *buf, size_t count)
207
{
208
int ret = priv->bitstream_burst_write(priv, buf, count);
209
210
if (ret)
211
sysconfig_burst_write_complete(priv);
212
213
return ret;
214
}
215
216
static int sysconfig_isc_disable(struct sysconfig_priv *priv)
217
{
218
const u8 isc_disable[] = SYSCONFIG_ISC_DISABLE;
219
220
return sysconfig_cmd_write(priv, isc_disable, sizeof(isc_disable));
221
}
222
223
static void sysconfig_cleanup(struct sysconfig_priv *priv)
224
{
225
sysconfig_isc_erase(priv);
226
sysconfig_refresh(priv);
227
}
228
229
static int sysconfig_isc_finish(struct sysconfig_priv *priv)
230
{
231
struct gpio_desc *done_gpio = priv->done;
232
u32 status;
233
int ret;
234
235
if (done_gpio) {
236
ret = sysconfig_isc_disable(priv);
237
if (ret)
238
return ret;
239
240
return sysconfig_poll_gpio(done_gpio, true);
241
}
242
243
ret = sysconfig_poll_status(priv, &status);
244
if (ret)
245
return ret;
246
247
if ((status & SYSCONFIG_STATUS_DONE) &&
248
!(status & SYSCONFIG_STATUS_BUSY) &&
249
!(status & SYSCONFIG_STATUS_ERR))
250
return sysconfig_isc_disable(priv);
251
252
return -EFAULT;
253
}
254
255
static enum fpga_mgr_states sysconfig_ops_state(struct fpga_manager *mgr)
256
{
257
struct sysconfig_priv *priv = mgr->priv;
258
struct gpio_desc *done = priv->done;
259
u32 status;
260
int ret;
261
262
if (done && (gpiod_get_value(done) > 0))
263
return FPGA_MGR_STATE_OPERATING;
264
265
ret = sysconfig_read_status(priv, &status);
266
if (!ret && (status & SYSCONFIG_STATUS_DONE))
267
return FPGA_MGR_STATE_OPERATING;
268
269
return FPGA_MGR_STATE_UNKNOWN;
270
}
271
272
static int sysconfig_ops_write_init(struct fpga_manager *mgr,
273
struct fpga_image_info *info,
274
const char *buf, size_t count)
275
{
276
struct sysconfig_priv *priv = mgr->priv;
277
struct device *dev = &mgr->dev;
278
int ret;
279
280
if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
281
dev_err(dev, "Partial reconfiguration is not supported\n");
282
return -EOPNOTSUPP;
283
}
284
285
/* Enter program mode */
286
ret = sysconfig_refresh(priv);
287
if (ret) {
288
dev_err(dev, "Failed to go to program mode\n");
289
return ret;
290
}
291
292
/* Enter ISC mode */
293
ret = sysconfig_isc_init(priv);
294
if (ret) {
295
dev_err(dev, "Failed to go to ISC mode\n");
296
return ret;
297
}
298
299
/* Initialize the Address Shift Register */
300
ret = sysconfig_lsc_init_addr(priv);
301
if (ret) {
302
dev_err(dev,
303
"Failed to initialize the Address Shift Register\n");
304
return ret;
305
}
306
307
/* Prepare for bitstream burst write */
308
ret = sysconfig_burst_write_init(priv);
309
if (ret)
310
dev_err(dev, "Failed to prepare for bitstream burst write\n");
311
312
return ret;
313
}
314
315
static int sysconfig_ops_write(struct fpga_manager *mgr, const char *buf,
316
size_t count)
317
{
318
return sysconfig_bitstream_burst_write(mgr->priv, buf, count);
319
}
320
321
static int sysconfig_ops_write_complete(struct fpga_manager *mgr,
322
struct fpga_image_info *info)
323
{
324
struct sysconfig_priv *priv = mgr->priv;
325
struct device *dev = &mgr->dev;
326
int ret;
327
328
ret = sysconfig_burst_write_complete(priv);
329
if (!ret)
330
ret = sysconfig_poll_busy(priv);
331
332
if (ret) {
333
dev_err(dev, "Error while waiting bitstream write to finish\n");
334
goto fail;
335
}
336
337
ret = sysconfig_isc_finish(priv);
338
339
fail:
340
if (ret)
341
sysconfig_cleanup(priv);
342
343
return ret;
344
}
345
346
static const struct fpga_manager_ops sysconfig_fpga_mgr_ops = {
347
.state = sysconfig_ops_state,
348
.write_init = sysconfig_ops_write_init,
349
.write = sysconfig_ops_write,
350
.write_complete = sysconfig_ops_write_complete,
351
};
352
353
int sysconfig_probe(struct sysconfig_priv *priv)
354
{
355
struct gpio_desc *program, *init, *done;
356
struct device *dev = priv->dev;
357
struct fpga_manager *mgr;
358
359
if (!dev)
360
return -ENODEV;
361
362
if (!priv->command_transfer ||
363
!priv->bitstream_burst_write_init ||
364
!priv->bitstream_burst_write ||
365
!priv->bitstream_burst_write_complete) {
366
dev_err(dev, "Essential callback is missing\n");
367
return -EINVAL;
368
}
369
370
program = devm_gpiod_get_optional(dev, "program", GPIOD_OUT_LOW);
371
if (IS_ERR(program))
372
return dev_err_probe(dev, PTR_ERR(program),
373
"Failed to get PROGRAM GPIO\n");
374
375
init = devm_gpiod_get_optional(dev, "init", GPIOD_IN);
376
if (IS_ERR(init))
377
return dev_err_probe(dev, PTR_ERR(init),
378
"Failed to get INIT GPIO\n");
379
380
done = devm_gpiod_get_optional(dev, "done", GPIOD_IN);
381
if (IS_ERR(done))
382
return dev_err_probe(dev, PTR_ERR(done),
383
"Failed to get DONE GPIO\n");
384
385
priv->program = program;
386
priv->init = init;
387
priv->done = done;
388
389
mgr = devm_fpga_mgr_register(dev, "Lattice sysCONFIG FPGA Manager",
390
&sysconfig_fpga_mgr_ops, priv);
391
392
return PTR_ERR_OR_ZERO(mgr);
393
}
394
EXPORT_SYMBOL(sysconfig_probe);
395
396
MODULE_DESCRIPTION("Lattice sysCONFIG FPGA Manager Core");
397
MODULE_LICENSE("GPL");
398
399