summaryrefslogtreecommitdiffstats
path: root/drivers/fpga/stratix10-soc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-12-28 23:54:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-12-28 23:54:57 -0500
commit457fa3469a65a524be04412f5cd497fa3b11c9fd (patch)
treee826786d7838668595dfac115ced53b32e5c97b9 /drivers/fpga/stratix10-soc.c
parentb07039b79c9ea64c1eacda1e01d645082e4a0d5d (diff)
parentfbc4904c287778ddb74bf6060ac9dec51992fc53 (diff)
Merge tag 'char-misc-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH: "Here is the big set of char and misc driver patches for 4.21-rc1. Lots of different types of driver things in here, as this tree seems to be the "collection of various driver subsystems not big enough to have their own git tree" lately. Anyway, some highlights of the changes in here: - binderfs: is it a rule that all driver subsystems will eventually grow to have their own filesystem? Binder now has one to handle the use of it in containerized systems. This was discussed at the Plumbers conference a few months ago and knocked into mergable shape very fast by Christian Brauner. Who also has signed up to be another binder maintainer, showing a distinct lack of good judgement :) - binder updates and fixes - mei driver updates - fpga driver updates and additions - thunderbolt driver updates - soundwire driver updates - extcon driver updates - nvmem driver updates - hyper-v driver updates - coresight driver updates - pvpanic driver additions and reworking for more device support - lp driver updates. Yes really, it's _finally_ moved to the proper parallal port driver model, something I never thought I would see happen. Good stuff. - other tiny driver updates and fixes. All of these have been in linux-next for a while with no reported issues" * tag 'char-misc-4.21-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (116 commits) MAINTAINERS: add another Android binder maintainer intel_th: msu: Fix an off-by-one in attribute store stm class: Add a reference to the SyS-T document stm class: Fix a module refcount leak in policy creation error path char: lp: use new parport device model char: lp: properly count the lp devices char: lp: use first unused lp number while registering char: lp: detach the device when parallel port is removed char: lp: introduce list to save port number bus: qcom: remove duplicated include from qcom-ebi2.c VMCI: Use memdup_user() rather than duplicating its implementation char/rtc: Use of_node_name_eq for node name comparisons misc: mic: fix a DMA pool free failure ptp: fix an IS_ERR() vs NULL check genwqe: Fix size check binder: implement binderfs binder: fix use-after-free due to ksys_close() during fdget() bus: fsl-mc: remove duplicated include files bus: fsl-mc: explicitly define the fsl_mc_command endianness misc: ti-st: make array read_ver_cmd static, shrinks object size ...
Diffstat (limited to 'drivers/fpga/stratix10-soc.c')
-rw-r--r--drivers/fpga/stratix10-soc.c535
1 files changed, 535 insertions, 0 deletions
diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c
new file mode 100644
index 000000000000..a1a09e04fab8
--- /dev/null
+++ b/drivers/fpga/stratix10-soc.c
@@ -0,0 +1,535 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * FPGA Manager Driver for Intel Stratix10 SoC
4 *
5 * Copyright (C) 2018 Intel Corporation
6 */
7#include <linux/completion.h>
8#include <linux/fpga/fpga-mgr.h>
9#include <linux/firmware/intel/stratix10-svc-client.h>
10#include <linux/module.h>
11#include <linux/of.h>
12#include <linux/of_platform.h>
13
14/*
15 * FPGA programming requires a higher level of privilege (EL3), per the SoC
16 * design.
17 */
18#define NUM_SVC_BUFS 4
19#define SVC_BUF_SIZE SZ_512K
20
21/* Indicates buffer is in use if set */
22#define SVC_BUF_LOCK 0
23
24#define S10_BUFFER_TIMEOUT (msecs_to_jiffies(SVC_RECONFIG_BUFFER_TIMEOUT_MS))
25#define S10_RECONFIG_TIMEOUT (msecs_to_jiffies(SVC_RECONFIG_REQUEST_TIMEOUT_MS))
26
27/*
28 * struct s10_svc_buf
29 * buf: virtual address of buf provided by service layer
30 * lock: locked if buffer is in use
31 */
32struct s10_svc_buf {
33 char *buf;
34 unsigned long lock;
35};
36
37struct s10_priv {
38 struct stratix10_svc_chan *chan;
39 struct stratix10_svc_client client;
40 struct completion status_return_completion;
41 struct s10_svc_buf svc_bufs[NUM_SVC_BUFS];
42 unsigned long status;
43};
44
45static int s10_svc_send_msg(struct s10_priv *priv,
46 enum stratix10_svc_command_code command,
47 void *payload, u32 payload_length)
48{
49 struct stratix10_svc_chan *chan = priv->chan;
50 struct device *dev = priv->client.dev;
51 struct stratix10_svc_client_msg msg;
52 int ret;
53
54 dev_dbg(dev, "%s cmd=%d payload=%p length=%d\n",
55 __func__, command, payload, payload_length);
56
57 msg.command = command;
58 msg.payload = payload;
59 msg.payload_length = payload_length;
60
61 ret = stratix10_svc_send(chan, &msg);
62 dev_dbg(dev, "stratix10_svc_send returned status %d\n", ret);
63
64 return ret;
65}
66
67/*
68 * Free buffers allocated from the service layer's pool that are not in use.
69 * Return true when all buffers are freed.
70 */
71static bool s10_free_buffers(struct fpga_manager *mgr)
72{
73 struct s10_priv *priv = mgr->priv;
74 uint num_free = 0;
75 uint i;
76
77 for (i = 0; i < NUM_SVC_BUFS; i++) {
78 if (!priv->svc_bufs[i].buf) {
79 num_free++;
80 continue;
81 }
82
83 if (!test_and_set_bit_lock(SVC_BUF_LOCK,
84 &priv->svc_bufs[i].lock)) {
85 stratix10_svc_free_memory(priv->chan,
86 priv->svc_bufs[i].buf);
87 priv->svc_bufs[i].buf = NULL;
88 num_free++;
89 }
90 }
91
92 return num_free == NUM_SVC_BUFS;
93}
94
95/*
96 * Returns count of how many buffers are not in use.
97 */
98static uint s10_free_buffer_count(struct fpga_manager *mgr)
99{
100 struct s10_priv *priv = mgr->priv;
101 uint num_free = 0;
102 uint i;
103
104 for (i = 0; i < NUM_SVC_BUFS; i++)
105 if (!priv->svc_bufs[i].buf)
106 num_free++;
107
108 return num_free;
109}
110
111/*
112 * s10_unlock_bufs
113 * Given the returned buffer address, match that address to our buffer struct
114 * and unlock that buffer. This marks it as available to be refilled and sent
115 * (or freed).
116 * priv: private data
117 * kaddr: kernel address of buffer that was returned from service layer
118 */
119static void s10_unlock_bufs(struct s10_priv *priv, void *kaddr)
120{
121 uint i;
122
123 if (!kaddr)
124 return;
125
126 for (i = 0; i < NUM_SVC_BUFS; i++)
127 if (priv->svc_bufs[i].buf == kaddr) {
128 clear_bit_unlock(SVC_BUF_LOCK,
129 &priv->svc_bufs[i].lock);
130 return;
131 }
132
133 WARN(1, "Unknown buffer returned from service layer %p\n", kaddr);
134}
135
136/*
137 * s10_receive_callback - callback for service layer to use to provide client
138 * (this driver) messages received through the mailbox.
139 * client: service layer client struct
140 * data: message from service layer
141 */
142static void s10_receive_callback(struct stratix10_svc_client *client,
143 struct stratix10_svc_cb_data *data)
144{
145 struct s10_priv *priv = client->priv;
146 u32 status;
147 int i;
148
149 WARN_ONCE(!data, "%s: stratix10_svc_rc_data = NULL", __func__);
150
151 status = data->status;
152
153 /*
154 * Here we set status bits as we receive them. Elsewhere, we always use
155 * test_and_clear_bit() to check status in priv->status
156 */
157 for (i = 0; i <= SVC_STATUS_RECONFIG_ERROR; i++)
158 if (status & (1 << i))
159 set_bit(i, &priv->status);
160
161 if (status & BIT(SVC_STATUS_RECONFIG_BUFFER_DONE)) {
162 s10_unlock_bufs(priv, data->kaddr1);
163 s10_unlock_bufs(priv, data->kaddr2);
164 s10_unlock_bufs(priv, data->kaddr3);
165 }
166
167 complete(&priv->status_return_completion);
168}
169
170/*
171 * s10_ops_write_init - prepare for FPGA reconfiguration by requesting
172 * partial reconfig and allocating buffers from the service layer.
173 */
174static int s10_ops_write_init(struct fpga_manager *mgr,
175 struct fpga_image_info *info,
176 const char *buf, size_t count)
177{
178 struct s10_priv *priv = mgr->priv;
179 struct device *dev = priv->client.dev;
180 struct stratix10_svc_command_config_type ctype;
181 char *kbuf;
182 uint i;
183 int ret;
184
185 ctype.flags = 0;
186 if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
187 dev_dbg(dev, "Requesting partial reconfiguration.\n");
188 ctype.flags |= BIT(COMMAND_RECONFIG_FLAG_PARTIAL);
189 } else {
190 dev_dbg(dev, "Requesting full reconfiguration.\n");
191 }
192
193 reinit_completion(&priv->status_return_completion);
194 ret = s10_svc_send_msg(priv, COMMAND_RECONFIG,
195 &ctype, sizeof(ctype));
196 if (ret < 0)
197 goto init_done;
198
199 ret = wait_for_completion_interruptible_timeout(
200 &priv->status_return_completion, S10_RECONFIG_TIMEOUT);
201 if (!ret) {
202 dev_err(dev, "timeout waiting for RECONFIG_REQUEST\n");
203 ret = -ETIMEDOUT;
204 goto init_done;
205 }
206 if (ret < 0) {
207 dev_err(dev, "error (%d) waiting for RECONFIG_REQUEST\n", ret);
208 goto init_done;
209 }
210
211 ret = 0;
212 if (!test_and_clear_bit(SVC_STATUS_RECONFIG_REQUEST_OK,
213 &priv->status)) {
214 ret = -ETIMEDOUT;
215 goto init_done;
216 }
217
218 /* Allocate buffers from the service layer's pool. */
219 for (i = 0; i < NUM_SVC_BUFS; i++) {
220 kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE);
221 if (!kbuf) {
222 s10_free_buffers(mgr);
223 ret = -ENOMEM;
224 goto init_done;
225 }
226
227 priv->svc_bufs[i].buf = kbuf;
228 priv->svc_bufs[i].lock = 0;
229 }
230
231init_done:
232 stratix10_svc_done(priv->chan);
233 return ret;
234}
235
236/*
237 * s10_send_buf - send a buffer to the service layer queue
238 * mgr: fpga manager struct
239 * buf: fpga image buffer
240 * count: size of buf in bytes
241 * Returns # of bytes transferred or -ENOBUFS if the all the buffers are in use
242 * or if the service queue is full. Never returns 0.
243 */
244static int s10_send_buf(struct fpga_manager *mgr, const char *buf, size_t count)
245{
246 struct s10_priv *priv = mgr->priv;
247 struct device *dev = priv->client.dev;
248 void *svc_buf;
249 size_t xfer_sz;
250 int ret;
251 uint i;
252
253 /* get/lock a buffer that that's not being used */
254 for (i = 0; i < NUM_SVC_BUFS; i++)
255 if (!test_and_set_bit_lock(SVC_BUF_LOCK,
256 &priv->svc_bufs[i].lock))
257 break;
258
259 if (i == NUM_SVC_BUFS)
260 return -ENOBUFS;
261
262 xfer_sz = count < SVC_BUF_SIZE ? count : SVC_BUF_SIZE;
263
264 svc_buf = priv->svc_bufs[i].buf;
265 memcpy(svc_buf, buf, xfer_sz);
266 ret = s10_svc_send_msg(priv, COMMAND_RECONFIG_DATA_SUBMIT,
267 svc_buf, xfer_sz);
268 if (ret < 0) {
269 dev_err(dev,
270 "Error while sending data to service layer (%d)", ret);
271 clear_bit_unlock(SVC_BUF_LOCK, &priv->svc_bufs[i].lock);
272 return ret;
273 }
274
275 return xfer_sz;
276}
277
278/*
279 * Send a FPGA image to privileged layers to write to the FPGA. When done
280 * sending, free all service layer buffers we allocated in write_init.
281 */
282static int s10_ops_write(struct fpga_manager *mgr, const char *buf,
283 size_t count)
284{
285 struct s10_priv *priv = mgr->priv;
286 struct device *dev = priv->client.dev;
287 long wait_status;
288 int sent = 0;
289 int ret = 0;
290
291 /*
292 * Loop waiting for buffers to be returned. When a buffer is returned,
293 * reuse it to send more data or free if if all data has been sent.
294 */
295 while (count > 0 || s10_free_buffer_count(mgr) != NUM_SVC_BUFS) {
296 reinit_completion(&priv->status_return_completion);
297
298 if (count > 0) {
299 sent = s10_send_buf(mgr, buf, count);
300 if (sent < 0)
301 continue;
302
303 count -= sent;
304 buf += sent;
305 } else {
306 if (s10_free_buffers(mgr))
307 return 0;
308
309 ret = s10_svc_send_msg(
310 priv, COMMAND_RECONFIG_DATA_CLAIM,
311 NULL, 0);
312 if (ret < 0)
313 break;
314 }
315
316 /*
317 * If callback hasn't already happened, wait for buffers to be
318 * returned from service layer
319 */
320 wait_status = 1; /* not timed out */
321 if (!priv->status)
322 wait_status = wait_for_completion_interruptible_timeout(
323 &priv->status_return_completion,
324 S10_BUFFER_TIMEOUT);
325
326 if (test_and_clear_bit(SVC_STATUS_RECONFIG_BUFFER_DONE,
327 &priv->status) ||
328 test_and_clear_bit(SVC_STATUS_RECONFIG_BUFFER_SUBMITTED,
329 &priv->status)) {
330 ret = 0;
331 continue;
332 }
333
334 if (test_and_clear_bit(SVC_STATUS_RECONFIG_ERROR,
335 &priv->status)) {
336 dev_err(dev, "ERROR - giving up - SVC_STATUS_RECONFIG_ERROR\n");
337 ret = -EFAULT;
338 break;
339 }
340
341 if (!wait_status) {
342 dev_err(dev, "timeout waiting for svc layer buffers\n");
343 ret = -ETIMEDOUT;
344 break;
345 }
346 if (wait_status < 0) {
347 ret = wait_status;
348 dev_err(dev,
349 "error (%d) waiting for svc layer buffers\n",
350 ret);
351 break;
352 }
353 }
354
355 if (!s10_free_buffers(mgr))
356 dev_err(dev, "%s not all buffers were freed\n", __func__);
357
358 return ret;
359}
360
361static int s10_ops_write_complete(struct fpga_manager *mgr,
362 struct fpga_image_info *info)
363{
364 struct s10_priv *priv = mgr->priv;
365 struct device *dev = priv->client.dev;
366 unsigned long timeout;
367 int ret;
368
369 timeout = usecs_to_jiffies(info->config_complete_timeout_us);
370
371 do {
372 reinit_completion(&priv->status_return_completion);
373
374 ret = s10_svc_send_msg(priv, COMMAND_RECONFIG_STATUS, NULL, 0);
375 if (ret < 0)
376 break;
377
378 ret = wait_for_completion_interruptible_timeout(
379 &priv->status_return_completion, timeout);
380 if (!ret) {
381 dev_err(dev,
382 "timeout waiting for RECONFIG_COMPLETED\n");
383 ret = -ETIMEDOUT;
384 break;
385 }
386 if (ret < 0) {
387 dev_err(dev,
388 "error (%d) waiting for RECONFIG_COMPLETED\n",
389 ret);
390 break;
391 }
392 /* Not error or timeout, so ret is # of jiffies until timeout */
393 timeout = ret;
394 ret = 0;
395
396 if (test_and_clear_bit(SVC_STATUS_RECONFIG_COMPLETED,
397 &priv->status))
398 break;
399
400 if (test_and_clear_bit(SVC_STATUS_RECONFIG_ERROR,
401 &priv->status)) {
402 dev_err(dev, "ERROR - giving up - SVC_STATUS_RECONFIG_ERROR\n");
403 ret = -EFAULT;
404 break;
405 }
406 } while (1);
407
408 stratix10_svc_done(priv->chan);
409
410 return ret;
411}
412
413static enum fpga_mgr_states s10_ops_state(struct fpga_manager *mgr)
414{
415 return FPGA_MGR_STATE_UNKNOWN;
416}
417
418static const struct fpga_manager_ops s10_ops = {
419 .state = s10_ops_state,
420 .write_init = s10_ops_write_init,
421 .write = s10_ops_write,
422 .write_complete = s10_ops_write_complete,
423};
424
425static int s10_probe(struct platform_device *pdev)
426{
427 struct device *dev = &pdev->dev;
428 struct s10_priv *priv;
429 struct fpga_manager *mgr;
430 int ret;
431
432 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
433 if (!priv)
434 return -ENOMEM;
435
436 priv->client.dev = dev;
437 priv->client.receive_cb = s10_receive_callback;
438 priv->client.priv = priv;
439
440 priv->chan = stratix10_svc_request_channel_byname(&priv->client,
441 SVC_CLIENT_FPGA);
442 if (IS_ERR(priv->chan)) {
443 dev_err(dev, "couldn't get service channel (%s)\n",
444 SVC_CLIENT_FPGA);
445 return PTR_ERR(priv->chan);
446 }
447
448 init_completion(&priv->status_return_completion);
449
450 mgr = fpga_mgr_create(dev, "Stratix10 SOC FPGA Manager",
451 &s10_ops, priv);
452 if (!mgr) {
453 dev_err(dev, "unable to create FPGA manager\n");
454 ret = -ENOMEM;
455 goto probe_err;
456 }
457
458 ret = fpga_mgr_register(mgr);
459 if (ret) {
460 dev_err(dev, "unable to register FPGA manager\n");
461 fpga_mgr_free(mgr);
462 goto probe_err;
463 }
464
465 platform_set_drvdata(pdev, mgr);
466 return ret;
467
468probe_err:
469 stratix10_svc_free_channel(priv->chan);
470 return ret;
471}
472
473static int s10_remove(struct platform_device *pdev)
474{
475 struct fpga_manager *mgr = platform_get_drvdata(pdev);
476 struct s10_priv *priv = mgr->priv;
477
478 fpga_mgr_unregister(mgr);
479 stratix10_svc_free_channel(priv->chan);
480
481 return 0;
482}
483
484static const struct of_device_id s10_of_match[] = {
485 { .compatible = "intel,stratix10-soc-fpga-mgr", },
486 {},
487};
488
489MODULE_DEVICE_TABLE(of, s10_of_match);
490
491static struct platform_driver s10_driver = {
492 .probe = s10_probe,
493 .remove = s10_remove,
494 .driver = {
495 .name = "Stratix10 SoC FPGA manager",
496 .of_match_table = of_match_ptr(s10_of_match),
497 },
498};
499
500static int __init s10_init(void)
501{
502 struct device_node *fw_np;
503 struct device_node *np;
504 int ret;
505
506 fw_np = of_find_node_by_name(NULL, "svc");
507 if (!fw_np)
508 return -ENODEV;
509
510 np = of_find_matching_node(fw_np, s10_of_match);
511 if (!np) {
512 of_node_put(fw_np);
513 return -ENODEV;
514 }
515
516 of_node_put(np);
517 ret = of_platform_populate(fw_np, s10_of_match, NULL, NULL);
518 of_node_put(fw_np);
519 if (ret)
520 return ret;
521
522 return platform_driver_register(&s10_driver);
523}
524
525static void __exit s10_exit(void)
526{
527 return platform_driver_unregister(&s10_driver);
528}
529
530module_init(s10_init);
531module_exit(s10_exit);
532
533MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
534MODULE_DESCRIPTION("Intel Stratix 10 SOC FPGA Manager");
535MODULE_LICENSE("GPL v2");