]> Git Repo - linux.git/blob - drivers/fpga/fpga-region.c
fpga: region: add fpga_region_class_find
[linux.git] / drivers / fpga / fpga-region.c
1 /*
2  * FPGA Region - Device Tree support for FPGA programming under Linux
3  *
4  *  Copyright (C) 2013-2016 Altera Corporation
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <linux/fpga/fpga-bridge.h>
20 #include <linux/fpga/fpga-mgr.h>
21 #include <linux/fpga/fpga-region.h>
22 #include <linux/idr.h>
23 #include <linux/kernel.h>
24 #include <linux/list.h>
25 #include <linux/module.h>
26 #include <linux/of_platform.h>
27 #include <linux/slab.h>
28 #include <linux/spinlock.h>
29
30 static DEFINE_IDA(fpga_region_ida);
31 static struct class *fpga_region_class;
32
33 struct fpga_region *fpga_region_class_find(
34         struct device *start, const void *data,
35         int (*match)(struct device *, const void *))
36 {
37         struct device *dev;
38
39         dev = class_find_device(fpga_region_class, start, data, match);
40         if (!dev)
41                 return NULL;
42
43         return to_fpga_region(dev);
44 }
45 EXPORT_SYMBOL_GPL(fpga_region_class_find);
46
47 static const struct of_device_id fpga_region_of_match[] = {
48         { .compatible = "fpga-region", },
49         {},
50 };
51 MODULE_DEVICE_TABLE(of, fpga_region_of_match);
52
53 static int fpga_region_of_node_match(struct device *dev, const void *data)
54 {
55         return dev->of_node == data;
56 }
57
58 /**
59  * of_fpga_region_find - find FPGA region
60  * @np: device node of FPGA Region
61  *
62  * Caller will need to put_device(&region->dev) when done.
63  *
64  * Returns FPGA Region struct or NULL
65  */
66 static struct fpga_region *of_fpga_region_find(struct device_node *np)
67 {
68         return fpga_region_class_find(NULL, np, fpga_region_of_node_match);
69 }
70
71 /**
72  * fpga_region_get - get an exclusive reference to a fpga region
73  * @region: FPGA Region struct
74  *
75  * Caller should call fpga_region_put() when done with region.
76  *
77  * Return fpga_region struct if successful.
78  * Return -EBUSY if someone already has a reference to the region.
79  * Return -ENODEV if @np is not a FPGA Region.
80  */
81 static struct fpga_region *fpga_region_get(struct fpga_region *region)
82 {
83         struct device *dev = &region->dev;
84
85         if (!mutex_trylock(&region->mutex)) {
86                 dev_dbg(dev, "%s: FPGA Region already in use\n", __func__);
87                 return ERR_PTR(-EBUSY);
88         }
89
90         get_device(dev);
91         if (!try_module_get(dev->parent->driver->owner)) {
92                 put_device(dev);
93                 mutex_unlock(&region->mutex);
94                 return ERR_PTR(-ENODEV);
95         }
96
97         dev_dbg(dev, "get\n");
98
99         return region;
100 }
101
102 /**
103  * fpga_region_put - release a reference to a region
104  *
105  * @region: FPGA region
106  */
107 static void fpga_region_put(struct fpga_region *region)
108 {
109         struct device *dev = &region->dev;
110
111         dev_dbg(dev, "put\n");
112
113         module_put(dev->parent->driver->owner);
114         put_device(dev);
115         mutex_unlock(&region->mutex);
116 }
117
118 /**
119  * of_fpga_region_get_mgr - get reference for FPGA manager
120  * @np: device node of FPGA region
121  *
122  * Get FPGA Manager from "fpga-mgr" property or from ancestor region.
123  *
124  * Caller should call fpga_mgr_put() when done with manager.
125  *
126  * Return: fpga manager struct or IS_ERR() condition containing error code.
127  */
128 static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np)
129 {
130         struct device_node  *mgr_node;
131         struct fpga_manager *mgr;
132
133         of_node_get(np);
134         while (np) {
135                 if (of_device_is_compatible(np, "fpga-region")) {
136                         mgr_node = of_parse_phandle(np, "fpga-mgr", 0);
137                         if (mgr_node) {
138                                 mgr = of_fpga_mgr_get(mgr_node);
139                                 of_node_put(np);
140                                 return mgr;
141                         }
142                 }
143                 np = of_get_next_parent(np);
144         }
145         of_node_put(np);
146
147         return ERR_PTR(-EINVAL);
148 }
149
150 /**
151  * of_fpga_region_get_bridges - create a list of bridges
152  * @region: FPGA region
153  *
154  * Create a list of bridges including the parent bridge and the bridges
155  * specified by "fpga-bridges" property.  Note that the
156  * fpga_bridges_enable/disable/put functions are all fine with an empty list
157  * if that happens.
158  *
159  * Caller should call fpga_bridges_put(&region->bridge_list) when
160  * done with the bridges.
161  *
162  * Return 0 for success (even if there are no bridges specified)
163  * or -EBUSY if any of the bridges are in use.
164  */
165 static int of_fpga_region_get_bridges(struct fpga_region *region)
166 {
167         struct device *dev = &region->dev;
168         struct device_node *region_np = dev->of_node;
169         struct fpga_image_info *info = region->info;
170         struct device_node *br, *np, *parent_br = NULL;
171         int i, ret;
172
173         /* If parent is a bridge, add to list */
174         ret = of_fpga_bridge_get_to_list(region_np->parent, info,
175                                          &region->bridge_list);
176
177         /* -EBUSY means parent is a bridge that is under use. Give up. */
178         if (ret == -EBUSY)
179                 return ret;
180
181         /* Zero return code means parent was a bridge and was added to list. */
182         if (!ret)
183                 parent_br = region_np->parent;
184
185         /* If overlay has a list of bridges, use it. */
186         if (of_parse_phandle(info->overlay, "fpga-bridges", 0))
187                 np = info->overlay;
188         else
189                 np = region_np;
190
191         for (i = 0; ; i++) {
192                 br = of_parse_phandle(np, "fpga-bridges", i);
193                 if (!br)
194                         break;
195
196                 /* If parent bridge is in list, skip it. */
197                 if (br == parent_br)
198                         continue;
199
200                 /* If node is a bridge, get it and add to list */
201                 ret = of_fpga_bridge_get_to_list(br, info,
202                                                  &region->bridge_list);
203
204                 /* If any of the bridges are in use, give up */
205                 if (ret == -EBUSY) {
206                         fpga_bridges_put(&region->bridge_list);
207                         return -EBUSY;
208                 }
209         }
210
211         return 0;
212 }
213
214 /**
215  * fpga_region_program_fpga - program FPGA
216  * @region: FPGA region
217  * Program an FPGA using fpga image info (region->info).
218  * Return 0 for success or negative error code.
219  */
220 int fpga_region_program_fpga(struct fpga_region *region)
221 {
222         struct device *dev = &region->dev;
223         struct fpga_image_info *info = region->info;
224         int ret;
225
226         region = fpga_region_get(region);
227         if (IS_ERR(region)) {
228                 dev_err(dev, "failed to get FPGA region\n");
229                 return PTR_ERR(region);
230         }
231
232         ret = fpga_mgr_lock(region->mgr);
233         if (ret) {
234                 dev_err(dev, "FPGA manager is busy\n");
235                 goto err_put_region;
236         }
237
238         /*
239          * In some cases, we already have a list of bridges in the
240          * fpga region struct.  Or we don't have any bridges.
241          */
242         if (region->get_bridges) {
243                 ret = region->get_bridges(region);
244                 if (ret) {
245                         dev_err(dev, "failed to get fpga region bridges\n");
246                         goto err_unlock_mgr;
247                 }
248         }
249
250         ret = fpga_bridges_disable(&region->bridge_list);
251         if (ret) {
252                 dev_err(dev, "failed to disable bridges\n");
253                 goto err_put_br;
254         }
255
256         ret = fpga_mgr_load(region->mgr, info);
257         if (ret) {
258                 dev_err(dev, "failed to load FPGA image\n");
259                 goto err_put_br;
260         }
261
262         ret = fpga_bridges_enable(&region->bridge_list);
263         if (ret) {
264                 dev_err(dev, "failed to enable region bridges\n");
265                 goto err_put_br;
266         }
267
268         fpga_mgr_unlock(region->mgr);
269         fpga_region_put(region);
270
271         return 0;
272
273 err_put_br:
274         if (region->get_bridges)
275                 fpga_bridges_put(&region->bridge_list);
276 err_unlock_mgr:
277         fpga_mgr_unlock(region->mgr);
278 err_put_region:
279         fpga_region_put(region);
280
281         return ret;
282 }
283 EXPORT_SYMBOL_GPL(fpga_region_program_fpga);
284
285 /**
286  * child_regions_with_firmware
287  * @overlay: device node of the overlay
288  *
289  * If the overlay adds child FPGA regions, they are not allowed to have
290  * firmware-name property.
291  *
292  * Return 0 for OK or -EINVAL if child FPGA region adds firmware-name.
293  */
294 static int child_regions_with_firmware(struct device_node *overlay)
295 {
296         struct device_node *child_region;
297         const char *child_firmware_name;
298         int ret = 0;
299
300         of_node_get(overlay);
301
302         child_region = of_find_matching_node(overlay, fpga_region_of_match);
303         while (child_region) {
304                 if (!of_property_read_string(child_region, "firmware-name",
305                                              &child_firmware_name)) {
306                         ret = -EINVAL;
307                         break;
308                 }
309                 child_region = of_find_matching_node(child_region,
310                                                      fpga_region_of_match);
311         }
312
313         of_node_put(child_region);
314
315         if (ret)
316                 pr_err("firmware-name not allowed in child FPGA region: %pOF",
317                        child_region);
318
319         return ret;
320 }
321
322 /**
323  * of_fpga_region_parse_ov - parse and check overlay applied to region
324  *
325  * @region: FPGA region
326  * @overlay: overlay applied to the FPGA region
327  *
328  * Given an overlay applied to a FPGA region, parse the FPGA image specific
329  * info in the overlay and do some checking.
330  *
331  * Returns:
332  *   NULL if overlay doesn't direct us to program the FPGA.
333  *   fpga_image_info struct if there is an image to program.
334  *   error code for invalid overlay.
335  */
336 static struct fpga_image_info *of_fpga_region_parse_ov(
337                                                 struct fpga_region *region,
338                                                 struct device_node *overlay)
339 {
340         struct device *dev = &region->dev;
341         struct fpga_image_info *info;
342         const char *firmware_name;
343         int ret;
344
345         if (region->info) {
346                 dev_err(dev, "Region already has overlay applied.\n");
347                 return ERR_PTR(-EINVAL);
348         }
349
350         /*
351          * Reject overlay if child FPGA Regions added in the overlay have
352          * firmware-name property (would mean that an FPGA region that has
353          * not been added to the live tree yet is doing FPGA programming).
354          */
355         ret = child_regions_with_firmware(overlay);
356         if (ret)
357                 return ERR_PTR(ret);
358
359         info = fpga_image_info_alloc(dev);
360         if (!info)
361                 return ERR_PTR(-ENOMEM);
362
363         info->overlay = overlay;
364
365         /* Read FPGA region properties from the overlay */
366         if (of_property_read_bool(overlay, "partial-fpga-config"))
367                 info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
368
369         if (of_property_read_bool(overlay, "external-fpga-config"))
370                 info->flags |= FPGA_MGR_EXTERNAL_CONFIG;
371
372         if (of_property_read_bool(overlay, "encrypted-fpga-config"))
373                 info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM;
374
375         if (!of_property_read_string(overlay, "firmware-name",
376                                      &firmware_name)) {
377                 info->firmware_name = devm_kstrdup(dev, firmware_name,
378                                                    GFP_KERNEL);
379                 if (!info->firmware_name)
380                         return ERR_PTR(-ENOMEM);
381         }
382
383         of_property_read_u32(overlay, "region-unfreeze-timeout-us",
384                              &info->enable_timeout_us);
385
386         of_property_read_u32(overlay, "region-freeze-timeout-us",
387                              &info->disable_timeout_us);
388
389         of_property_read_u32(overlay, "config-complete-timeout-us",
390                              &info->config_complete_timeout_us);
391
392         /* If overlay is not programming the FPGA, don't need FPGA image info */
393         if (!info->firmware_name) {
394                 ret = 0;
395                 goto ret_no_info;
396         }
397
398         /*
399          * If overlay informs us FPGA was externally programmed, specifying
400          * firmware here would be ambiguous.
401          */
402         if (info->flags & FPGA_MGR_EXTERNAL_CONFIG) {
403                 dev_err(dev, "error: specified firmware and external-fpga-config");
404                 ret = -EINVAL;
405                 goto ret_no_info;
406         }
407
408         return info;
409 ret_no_info:
410         fpga_image_info_free(info);
411         return ERR_PTR(ret);
412 }
413
414 /**
415  * of_fpga_region_notify_pre_apply - pre-apply overlay notification
416  *
417  * @region: FPGA region that the overlay was applied to
418  * @nd: overlay notification data
419  *
420  * Called when an overlay targeted to a FPGA Region is about to be applied.
421  * Parses the overlay for properties that influence how the FPGA will be
422  * programmed and does some checking. If the checks pass, programs the FPGA.
423  * If the checks fail, overlay is rejected and does not get added to the
424  * live tree.
425  *
426  * Returns 0 for success or negative error code for failure.
427  */
428 static int of_fpga_region_notify_pre_apply(struct fpga_region *region,
429                                            struct of_overlay_notify_data *nd)
430 {
431         struct device *dev = &region->dev;
432         struct fpga_image_info *info;
433         int ret;
434
435         if (region->info) {
436                 dev_err(dev, "Region already has overlay applied.\n");
437                 return -EINVAL;
438         }
439
440         info = of_fpga_region_parse_ov(region, nd->overlay);
441         if (IS_ERR(info))
442                 return PTR_ERR(info);
443
444         if (!info)
445                 return 0;
446
447         region->info = info;
448         ret = fpga_region_program_fpga(region);
449         if (ret) {
450                 /* error; reject overlay */
451                 fpga_image_info_free(info);
452                 region->info = NULL;
453         }
454
455         return ret;
456 }
457
458 /**
459  * of_fpga_region_notify_post_remove - post-remove overlay notification
460  *
461  * @region: FPGA region that was targeted by the overlay that was removed
462  * @nd: overlay notification data
463  *
464  * Called after an overlay has been removed if the overlay's target was a
465  * FPGA region.
466  */
467 static void of_fpga_region_notify_post_remove(struct fpga_region *region,
468                                               struct of_overlay_notify_data *nd)
469 {
470         fpga_bridges_disable(&region->bridge_list);
471         fpga_bridges_put(&region->bridge_list);
472         fpga_image_info_free(region->info);
473         region->info = NULL;
474 }
475
476 /**
477  * of_fpga_region_notify - reconfig notifier for dynamic DT changes
478  * @nb:         notifier block
479  * @action:     notifier action
480  * @arg:        reconfig data
481  *
482  * This notifier handles programming a FPGA when a "firmware-name" property is
483  * added to a fpga-region.
484  *
485  * Returns NOTIFY_OK or error if FPGA programming fails.
486  */
487 static int of_fpga_region_notify(struct notifier_block *nb,
488                                  unsigned long action, void *arg)
489 {
490         struct of_overlay_notify_data *nd = arg;
491         struct fpga_region *region;
492         int ret;
493
494         switch (action) {
495         case OF_OVERLAY_PRE_APPLY:
496                 pr_debug("%s OF_OVERLAY_PRE_APPLY\n", __func__);
497                 break;
498         case OF_OVERLAY_POST_APPLY:
499                 pr_debug("%s OF_OVERLAY_POST_APPLY\n", __func__);
500                 return NOTIFY_OK;       /* not for us */
501         case OF_OVERLAY_PRE_REMOVE:
502                 pr_debug("%s OF_OVERLAY_PRE_REMOVE\n", __func__);
503                 return NOTIFY_OK;       /* not for us */
504         case OF_OVERLAY_POST_REMOVE:
505                 pr_debug("%s OF_OVERLAY_POST_REMOVE\n", __func__);
506                 break;
507         default:                        /* should not happen */
508                 return NOTIFY_OK;
509         }
510
511         region = of_fpga_region_find(nd->target);
512         if (!region)
513                 return NOTIFY_OK;
514
515         ret = 0;
516         switch (action) {
517         case OF_OVERLAY_PRE_APPLY:
518                 ret = of_fpga_region_notify_pre_apply(region, nd);
519                 break;
520
521         case OF_OVERLAY_POST_REMOVE:
522                 of_fpga_region_notify_post_remove(region, nd);
523                 break;
524         }
525
526         put_device(&region->dev);
527
528         if (ret)
529                 return notifier_from_errno(ret);
530
531         return NOTIFY_OK;
532 }
533
534 static struct notifier_block fpga_region_of_nb = {
535         .notifier_call = of_fpga_region_notify,
536 };
537
538 int fpga_region_register(struct device *dev, struct fpga_region *region)
539 {
540         int id, ret = 0;
541
542         id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
543         if (id < 0)
544                 return id;
545
546         mutex_init(&region->mutex);
547         INIT_LIST_HEAD(&region->bridge_list);
548         device_initialize(&region->dev);
549         region->dev.class = fpga_region_class;
550         region->dev.parent = dev;
551         region->dev.of_node = dev->of_node;
552         region->dev.id = id;
553         dev_set_drvdata(dev, region);
554
555         ret = dev_set_name(&region->dev, "region%d", id);
556         if (ret)
557                 goto err_remove;
558
559         ret = device_add(&region->dev);
560         if (ret)
561                 goto err_remove;
562
563         return 0;
564
565 err_remove:
566         ida_simple_remove(&fpga_region_ida, id);
567         return ret;
568 }
569 EXPORT_SYMBOL_GPL(fpga_region_register);
570
571 int fpga_region_unregister(struct fpga_region *region)
572 {
573         device_unregister(&region->dev);
574
575         return 0;
576 }
577 EXPORT_SYMBOL_GPL(fpga_region_unregister);
578
579 static int of_fpga_region_probe(struct platform_device *pdev)
580 {
581         struct device *dev = &pdev->dev;
582         struct device_node *np = dev->of_node;
583         struct fpga_region *region;
584         struct fpga_manager *mgr;
585         int ret;
586
587         /* Find the FPGA mgr specified by region or parent region. */
588         mgr = of_fpga_region_get_mgr(np);
589         if (IS_ERR(mgr))
590                 return -EPROBE_DEFER;
591
592         region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL);
593         if (!region) {
594                 ret = -ENOMEM;
595                 goto eprobe_mgr_put;
596         }
597
598         region->mgr = mgr;
599
600         /* Specify how to get bridges for this type of region. */
601         region->get_bridges = of_fpga_region_get_bridges;
602
603         ret = fpga_region_register(dev, region);
604         if (ret)
605                 goto eprobe_mgr_put;
606
607         of_platform_populate(np, fpga_region_of_match, NULL, &region->dev);
608
609         dev_info(dev, "FPGA Region probed\n");
610
611         return 0;
612
613 eprobe_mgr_put:
614         fpga_mgr_put(mgr);
615         return ret;
616 }
617
618 static int of_fpga_region_remove(struct platform_device *pdev)
619 {
620         struct fpga_region *region = platform_get_drvdata(pdev);
621
622         fpga_region_unregister(region);
623         fpga_mgr_put(region->mgr);
624
625         return 0;
626 }
627
628 static struct platform_driver of_fpga_region_driver = {
629         .probe = of_fpga_region_probe,
630         .remove = of_fpga_region_remove,
631         .driver = {
632                 .name   = "fpga-region",
633                 .of_match_table = of_match_ptr(fpga_region_of_match),
634         },
635 };
636
637 static void fpga_region_dev_release(struct device *dev)
638 {
639         struct fpga_region *region = to_fpga_region(dev);
640
641         ida_simple_remove(&fpga_region_ida, region->dev.id);
642 }
643
644 /**
645  * fpga_region_init - init function for fpga_region class
646  * Creates the fpga_region class and registers a reconfig notifier.
647  */
648 static int __init fpga_region_init(void)
649 {
650         int ret;
651
652         fpga_region_class = class_create(THIS_MODULE, "fpga_region");
653         if (IS_ERR(fpga_region_class))
654                 return PTR_ERR(fpga_region_class);
655
656         fpga_region_class->dev_release = fpga_region_dev_release;
657
658         ret = of_overlay_notifier_register(&fpga_region_of_nb);
659         if (ret)
660                 goto err_class;
661
662         ret = platform_driver_register(&of_fpga_region_driver);
663         if (ret)
664                 goto err_plat;
665
666         return 0;
667
668 err_plat:
669         of_overlay_notifier_unregister(&fpga_region_of_nb);
670 err_class:
671         class_destroy(fpga_region_class);
672         ida_destroy(&fpga_region_ida);
673         return ret;
674 }
675
676 static void __exit fpga_region_exit(void)
677 {
678         platform_driver_unregister(&of_fpga_region_driver);
679         of_overlay_notifier_unregister(&fpga_region_of_nb);
680         class_destroy(fpga_region_class);
681         ida_destroy(&fpga_region_ida);
682 }
683
684 subsys_initcall(fpga_region_init);
685 module_exit(fpga_region_exit);
686
687 MODULE_DESCRIPTION("FPGA Region");
688 MODULE_AUTHOR("Alan Tull <[email protected]>");
689 MODULE_LICENSE("GPL v2");
This page took 0.070871 seconds and 4 git commands to generate.