1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/fpga/fpga-bridge.h>
20#include <linux/fpga/fpga-mgr.h>
21#include <linux/idr.h>
22#include <linux/kernel.h>
23#include <linux/list.h>
24#include <linux/module.h>
25#include <linux/of_platform.h>
26#include <linux/slab.h>
27#include <linux/spinlock.h>
28
29
30
31
32
33
34
35
36struct fpga_region {
37 struct device dev;
38 struct mutex mutex;
39 struct list_head bridge_list;
40 struct fpga_image_info *info;
41};
42
43#define to_fpga_region(d) container_of(d, struct fpga_region, dev)
44
45static DEFINE_IDA(fpga_region_ida);
46static struct class *fpga_region_class;
47
48static const struct of_device_id fpga_region_of_match[] = {
49 { .compatible = "fpga-region", },
50 {},
51};
52MODULE_DEVICE_TABLE(of, fpga_region_of_match);
53
54static int fpga_region_of_node_match(struct device *dev, const void *data)
55{
56 return dev->of_node == data;
57}
58
59
60
61
62
63
64
65static struct fpga_region *fpga_region_find(struct device_node *np)
66{
67 struct device *dev;
68
69 dev = class_find_device(fpga_region_class, NULL, np,
70 fpga_region_of_node_match);
71 if (!dev)
72 return NULL;
73
74 return to_fpga_region(dev);
75}
76
77
78
79
80
81
82
83
84
85
86
87static struct fpga_region *fpga_region_get(struct fpga_region *region)
88{
89 struct device *dev = ®ion->dev;
90
91 if (!mutex_trylock(®ion->mutex)) {
92 dev_dbg(dev, "%s: FPGA Region already in use\n", __func__);
93 return ERR_PTR(-EBUSY);
94 }
95
96 get_device(dev);
97 of_node_get(dev->of_node);
98 if (!try_module_get(dev->parent->driver->owner)) {
99 of_node_put(dev->of_node);
100 put_device(dev);
101 mutex_unlock(®ion->mutex);
102 return ERR_PTR(-ENODEV);
103 }
104
105 dev_dbg(®ion->dev, "get\n");
106
107 return region;
108}
109
110
111
112
113
114
115static void fpga_region_put(struct fpga_region *region)
116{
117 struct device *dev = ®ion->dev;
118
119 dev_dbg(®ion->dev, "put\n");
120
121 module_put(dev->parent->driver->owner);
122 of_node_put(dev->of_node);
123 put_device(dev);
124 mutex_unlock(®ion->mutex);
125}
126
127
128
129
130
131
132
133
134
135
136
137static struct fpga_manager *fpga_region_get_manager(struct fpga_region *region)
138{
139 struct device *dev = ®ion->dev;
140 struct device_node *np = dev->of_node;
141 struct device_node *mgr_node;
142 struct fpga_manager *mgr;
143
144 of_node_get(np);
145 while (np) {
146 if (of_device_is_compatible(np, "fpga-region")) {
147 mgr_node = of_parse_phandle(np, "fpga-mgr", 0);
148 if (mgr_node) {
149 mgr = of_fpga_mgr_get(mgr_node);
150 of_node_put(np);
151 return mgr;
152 }
153 }
154 np = of_get_next_parent(np);
155 }
156 of_node_put(np);
157
158 return ERR_PTR(-EINVAL);
159}
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177static int fpga_region_get_bridges(struct fpga_region *region,
178 struct device_node *overlay)
179{
180 struct device *dev = ®ion->dev;
181 struct device_node *region_np = dev->of_node;
182 struct device_node *br, *np, *parent_br = NULL;
183 int i, ret;
184
185
186 ret = fpga_bridge_get_to_list(region_np->parent, region->info,
187 ®ion->bridge_list);
188 if (ret == -EBUSY)
189 return ret;
190
191 if (!ret)
192 parent_br = region_np->parent;
193
194
195 if (of_parse_phandle(overlay, "fpga-bridges", 0))
196 np = overlay;
197 else
198 np = region_np;
199
200 for (i = 0; ; i++) {
201 br = of_parse_phandle(np, "fpga-bridges", i);
202 if (!br)
203 break;
204
205
206 if (br == parent_br)
207 continue;
208
209
210 ret = fpga_bridge_get_to_list(br, region->info,
211 ®ion->bridge_list);
212
213
214 if (ret == -EBUSY) {
215 fpga_bridges_put(®ion->bridge_list);
216 return -EBUSY;
217 }
218 }
219
220 return 0;
221}
222
223
224
225
226
227
228
229
230
231
232static int fpga_region_program_fpga(struct fpga_region *region,
233 const char *firmware_name,
234 struct device_node *overlay)
235{
236 struct fpga_manager *mgr;
237 int ret;
238
239 region = fpga_region_get(region);
240 if (IS_ERR(region)) {
241 pr_err("failed to get fpga region\n");
242 return PTR_ERR(region);
243 }
244
245 mgr = fpga_region_get_manager(region);
246 if (IS_ERR(mgr)) {
247 pr_err("failed to get fpga region manager\n");
248 ret = PTR_ERR(mgr);
249 goto err_put_region;
250 }
251
252 ret = fpga_region_get_bridges(region, overlay);
253 if (ret) {
254 pr_err("failed to get fpga region bridges\n");
255 goto err_put_mgr;
256 }
257
258 ret = fpga_bridges_disable(®ion->bridge_list);
259 if (ret) {
260 pr_err("failed to disable region bridges\n");
261 goto err_put_br;
262 }
263
264 ret = fpga_mgr_firmware_load(mgr, region->info, firmware_name);
265 if (ret) {
266 pr_err("failed to load fpga image\n");
267 goto err_put_br;
268 }
269
270 ret = fpga_bridges_enable(®ion->bridge_list);
271 if (ret) {
272 pr_err("failed to enable region bridges\n");
273 goto err_put_br;
274 }
275
276 fpga_mgr_put(mgr);
277 fpga_region_put(region);
278
279 return 0;
280
281err_put_br:
282 fpga_bridges_put(®ion->bridge_list);
283err_put_mgr:
284 fpga_mgr_put(mgr);
285err_put_region:
286 fpga_region_put(region);
287
288 return ret;
289}
290
291
292
293
294
295
296
297
298
299
300static int child_regions_with_firmware(struct device_node *overlay)
301{
302 struct device_node *child_region;
303 const char *child_firmware_name;
304 int ret = 0;
305
306 of_node_get(overlay);
307
308 child_region = of_find_matching_node(overlay, fpga_region_of_match);
309 while (child_region) {
310 if (!of_property_read_string(child_region, "firmware-name",
311 &child_firmware_name)) {
312 ret = -EINVAL;
313 break;
314 }
315 child_region = of_find_matching_node(child_region,
316 fpga_region_of_match);
317 }
318
319 of_node_put(child_region);
320
321 if (ret)
322 pr_err("firmware-name not allowed in child FPGA region: %pOF",
323 child_region);
324
325 return ret;
326}
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354static int fpga_region_notify_pre_apply(struct fpga_region *region,
355 struct of_overlay_notify_data *nd)
356{
357 const char *firmware_name = NULL;
358 struct fpga_image_info *info;
359 int ret;
360
361 info = devm_kzalloc(®ion->dev, sizeof(*info), GFP_KERNEL);
362 if (!info)
363 return -ENOMEM;
364
365 region->info = info;
366
367
368 ret = child_regions_with_firmware(nd->overlay);
369 if (ret)
370 return ret;
371
372
373 if (of_property_read_bool(nd->overlay, "partial-fpga-config"))
374 info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
375
376 if (of_property_read_bool(nd->overlay, "external-fpga-config"))
377 info->flags |= FPGA_MGR_EXTERNAL_CONFIG;
378
379 if (of_property_read_bool(nd->overlay, "encrypted-fpga-config"))
380 info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM;
381
382 of_property_read_string(nd->overlay, "firmware-name", &firmware_name);
383
384 of_property_read_u32(nd->overlay, "region-unfreeze-timeout-us",
385 &info->enable_timeout_us);
386
387 of_property_read_u32(nd->overlay, "region-freeze-timeout-us",
388 &info->disable_timeout_us);
389
390 of_property_read_u32(nd->overlay, "config-complete-timeout-us",
391 &info->config_complete_timeout_us);
392
393
394 if ((info->flags & FPGA_MGR_EXTERNAL_CONFIG) && firmware_name) {
395 pr_err("error: specified firmware and external-fpga-config");
396 return -EINVAL;
397 }
398
399
400 if (info->flags & FPGA_MGR_EXTERNAL_CONFIG)
401 return 0;
402
403
404 if (!firmware_name) {
405 pr_err("should specify firmware-name or external-fpga-config\n");
406 return -EINVAL;
407 }
408
409 return fpga_region_program_fpga(region, firmware_name, nd->overlay);
410}
411
412
413
414
415
416
417
418
419
420
421static void fpga_region_notify_post_remove(struct fpga_region *region,
422 struct of_overlay_notify_data *nd)
423{
424 fpga_bridges_disable(®ion->bridge_list);
425 fpga_bridges_put(®ion->bridge_list);
426 devm_kfree(®ion->dev, region->info);
427 region->info = NULL;
428}
429
430
431
432
433
434
435
436
437
438
439
440
441static int of_fpga_region_notify(struct notifier_block *nb,
442 unsigned long action, void *arg)
443{
444 struct of_overlay_notify_data *nd = arg;
445 struct fpga_region *region;
446 int ret;
447
448 switch (action) {
449 case OF_OVERLAY_PRE_APPLY:
450 pr_debug("%s OF_OVERLAY_PRE_APPLY\n", __func__);
451 break;
452 case OF_OVERLAY_POST_APPLY:
453 pr_debug("%s OF_OVERLAY_POST_APPLY\n", __func__);
454 return NOTIFY_OK;
455 case OF_OVERLAY_PRE_REMOVE:
456 pr_debug("%s OF_OVERLAY_PRE_REMOVE\n", __func__);
457 return NOTIFY_OK;
458 case OF_OVERLAY_POST_REMOVE:
459 pr_debug("%s OF_OVERLAY_POST_REMOVE\n", __func__);
460 break;
461 default:
462 return NOTIFY_OK;
463 }
464
465 region = fpga_region_find(nd->target);
466 if (!region)
467 return NOTIFY_OK;
468
469 ret = 0;
470 switch (action) {
471 case OF_OVERLAY_PRE_APPLY:
472 ret = fpga_region_notify_pre_apply(region, nd);
473 break;
474
475 case OF_OVERLAY_POST_REMOVE:
476 fpga_region_notify_post_remove(region, nd);
477 break;
478 }
479
480 put_device(®ion->dev);
481
482 if (ret)
483 return notifier_from_errno(ret);
484
485 return NOTIFY_OK;
486}
487
488static struct notifier_block fpga_region_of_nb = {
489 .notifier_call = of_fpga_region_notify,
490};
491
492static int fpga_region_probe(struct platform_device *pdev)
493{
494 struct device *dev = &pdev->dev;
495 struct device_node *np = dev->of_node;
496 struct fpga_region *region;
497 int id, ret = 0;
498
499 region = kzalloc(sizeof(*region), GFP_KERNEL);
500 if (!region)
501 return -ENOMEM;
502
503 id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
504 if (id < 0) {
505 ret = id;
506 goto err_kfree;
507 }
508
509 mutex_init(®ion->mutex);
510 INIT_LIST_HEAD(®ion->bridge_list);
511
512 device_initialize(®ion->dev);
513 region->dev.class = fpga_region_class;
514 region->dev.parent = dev;
515 region->dev.of_node = np;
516 region->dev.id = id;
517 dev_set_drvdata(dev, region);
518
519 ret = dev_set_name(®ion->dev, "region%d", id);
520 if (ret)
521 goto err_remove;
522
523 ret = device_add(®ion->dev);
524 if (ret)
525 goto err_remove;
526
527 of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev);
528
529 dev_info(dev, "FPGA Region probed\n");
530
531 return 0;
532
533err_remove:
534 ida_simple_remove(&fpga_region_ida, id);
535err_kfree:
536 kfree(region);
537
538 return ret;
539}
540
541static int fpga_region_remove(struct platform_device *pdev)
542{
543 struct fpga_region *region = platform_get_drvdata(pdev);
544
545 device_unregister(®ion->dev);
546
547 return 0;
548}
549
550static struct platform_driver fpga_region_driver = {
551 .probe = fpga_region_probe,
552 .remove = fpga_region_remove,
553 .driver = {
554 .name = "fpga-region",
555 .of_match_table = of_match_ptr(fpga_region_of_match),
556 },
557};
558
559static void fpga_region_dev_release(struct device *dev)
560{
561 struct fpga_region *region = to_fpga_region(dev);
562
563 ida_simple_remove(&fpga_region_ida, region->dev.id);
564 kfree(region);
565}
566
567
568
569
570
571static int __init fpga_region_init(void)
572{
573 int ret;
574
575 fpga_region_class = class_create(THIS_MODULE, "fpga_region");
576 if (IS_ERR(fpga_region_class))
577 return PTR_ERR(fpga_region_class);
578
579 fpga_region_class->dev_release = fpga_region_dev_release;
580
581 ret = of_overlay_notifier_register(&fpga_region_of_nb);
582 if (ret)
583 goto err_class;
584
585 ret = platform_driver_register(&fpga_region_driver);
586 if (ret)
587 goto err_plat;
588
589 return 0;
590
591err_plat:
592 of_overlay_notifier_unregister(&fpga_region_of_nb);
593err_class:
594 class_destroy(fpga_region_class);
595 ida_destroy(&fpga_region_ida);
596 return ret;
597}
598
599static void __exit fpga_region_exit(void)
600{
601 platform_driver_unregister(&fpga_region_driver);
602 of_overlay_notifier_unregister(&fpga_region_of_nb);
603 class_destroy(fpga_region_class);
604 ida_destroy(&fpga_region_ida);
605}
606
607subsys_initcall(fpga_region_init);
608module_exit(fpga_region_exit);
609
610MODULE_DESCRIPTION("FPGA Region");
611MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
612MODULE_LICENSE("GPL v2");
613