0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/fpga/fpga-bridge.h>
0009 #include <linux/fpga/fpga-mgr.h>
0010 #include <linux/fpga/fpga-region.h>
0011 #include <linux/idr.h>
0012 #include <linux/kernel.h>
0013 #include <linux/list.h>
0014 #include <linux/module.h>
0015 #include <linux/of_platform.h>
0016 #include <linux/slab.h>
0017 #include <linux/spinlock.h>
0018
0019 static const struct of_device_id fpga_region_of_match[] = {
0020 { .compatible = "fpga-region", },
0021 {},
0022 };
0023 MODULE_DEVICE_TABLE(of, fpga_region_of_match);
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 static struct fpga_region *of_fpga_region_find(struct device_node *np)
0034 {
0035 return fpga_region_class_find(NULL, np, device_match_of_node);
0036 }
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np)
0049 {
0050 struct device_node *mgr_node;
0051 struct fpga_manager *mgr;
0052
0053 of_node_get(np);
0054 while (np) {
0055 if (of_device_is_compatible(np, "fpga-region")) {
0056 mgr_node = of_parse_phandle(np, "fpga-mgr", 0);
0057 if (mgr_node) {
0058 mgr = of_fpga_mgr_get(mgr_node);
0059 of_node_put(mgr_node);
0060 of_node_put(np);
0061 return mgr;
0062 }
0063 }
0064 np = of_get_next_parent(np);
0065 }
0066 of_node_put(np);
0067
0068 return ERR_PTR(-EINVAL);
0069 }
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 static int of_fpga_region_get_bridges(struct fpga_region *region)
0087 {
0088 struct device *dev = ®ion->dev;
0089 struct device_node *region_np = dev->of_node;
0090 struct fpga_image_info *info = region->info;
0091 struct device_node *br, *np, *parent_br = NULL;
0092 int i, ret;
0093
0094
0095 ret = of_fpga_bridge_get_to_list(region_np->parent, info,
0096 ®ion->bridge_list);
0097
0098
0099 if (ret == -EBUSY)
0100 return ret;
0101
0102
0103 if (!ret)
0104 parent_br = region_np->parent;
0105
0106
0107 br = of_parse_phandle(info->overlay, "fpga-bridges", 0);
0108 if (br) {
0109 of_node_put(br);
0110 np = info->overlay;
0111 } else {
0112 np = region_np;
0113 }
0114
0115 for (i = 0; ; i++) {
0116 br = of_parse_phandle(np, "fpga-bridges", i);
0117 if (!br)
0118 break;
0119
0120
0121 if (br == parent_br) {
0122 of_node_put(br);
0123 continue;
0124 }
0125
0126
0127 ret = of_fpga_bridge_get_to_list(br, info,
0128 ®ion->bridge_list);
0129 of_node_put(br);
0130
0131
0132 if (ret == -EBUSY) {
0133 fpga_bridges_put(®ion->bridge_list);
0134 return -EBUSY;
0135 }
0136 }
0137
0138 return 0;
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150 static int child_regions_with_firmware(struct device_node *overlay)
0151 {
0152 struct device_node *child_region;
0153 const char *child_firmware_name;
0154 int ret = 0;
0155
0156 of_node_get(overlay);
0157
0158 child_region = of_find_matching_node(overlay, fpga_region_of_match);
0159 while (child_region) {
0160 if (!of_property_read_string(child_region, "firmware-name",
0161 &child_firmware_name)) {
0162 ret = -EINVAL;
0163 break;
0164 }
0165 child_region = of_find_matching_node(child_region,
0166 fpga_region_of_match);
0167 }
0168
0169 of_node_put(child_region);
0170
0171 if (ret)
0172 pr_err("firmware-name not allowed in child FPGA region: %pOF",
0173 child_region);
0174
0175 return ret;
0176 }
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192 static struct fpga_image_info *
0193 of_fpga_region_parse_ov(struct fpga_region *region,
0194 struct device_node *overlay)
0195 {
0196 struct device *dev = ®ion->dev;
0197 struct fpga_image_info *info;
0198 const char *firmware_name;
0199 int ret;
0200
0201 if (region->info) {
0202 dev_err(dev, "Region already has overlay applied.\n");
0203 return ERR_PTR(-EINVAL);
0204 }
0205
0206
0207
0208
0209
0210
0211 ret = child_regions_with_firmware(overlay);
0212 if (ret)
0213 return ERR_PTR(ret);
0214
0215 info = fpga_image_info_alloc(dev);
0216 if (!info)
0217 return ERR_PTR(-ENOMEM);
0218
0219 info->overlay = overlay;
0220
0221
0222 if (of_property_read_bool(overlay, "partial-fpga-config"))
0223 info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
0224
0225 if (of_property_read_bool(overlay, "external-fpga-config"))
0226 info->flags |= FPGA_MGR_EXTERNAL_CONFIG;
0227
0228 if (of_property_read_bool(overlay, "encrypted-fpga-config"))
0229 info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM;
0230
0231 if (!of_property_read_string(overlay, "firmware-name",
0232 &firmware_name)) {
0233 info->firmware_name = devm_kstrdup(dev, firmware_name,
0234 GFP_KERNEL);
0235 if (!info->firmware_name)
0236 return ERR_PTR(-ENOMEM);
0237 }
0238
0239 of_property_read_u32(overlay, "region-unfreeze-timeout-us",
0240 &info->enable_timeout_us);
0241
0242 of_property_read_u32(overlay, "region-freeze-timeout-us",
0243 &info->disable_timeout_us);
0244
0245 of_property_read_u32(overlay, "config-complete-timeout-us",
0246 &info->config_complete_timeout_us);
0247
0248
0249 if (!info->firmware_name) {
0250 ret = 0;
0251 goto ret_no_info;
0252 }
0253
0254
0255
0256
0257
0258 if (info->flags & FPGA_MGR_EXTERNAL_CONFIG) {
0259 dev_err(dev, "error: specified firmware and external-fpga-config");
0260 ret = -EINVAL;
0261 goto ret_no_info;
0262 }
0263
0264 return info;
0265 ret_no_info:
0266 fpga_image_info_free(info);
0267 return ERR_PTR(ret);
0268 }
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284 static int of_fpga_region_notify_pre_apply(struct fpga_region *region,
0285 struct of_overlay_notify_data *nd)
0286 {
0287 struct device *dev = ®ion->dev;
0288 struct fpga_image_info *info;
0289 int ret;
0290
0291 info = of_fpga_region_parse_ov(region, nd->overlay);
0292 if (IS_ERR(info))
0293 return PTR_ERR(info);
0294
0295
0296 if (!info)
0297 return 0;
0298
0299 if (region->info) {
0300 dev_err(dev, "Region already has overlay applied.\n");
0301 return -EINVAL;
0302 }
0303
0304 region->info = info;
0305 ret = fpga_region_program_fpga(region);
0306 if (ret) {
0307
0308 fpga_image_info_free(info);
0309 region->info = NULL;
0310 }
0311
0312 return ret;
0313 }
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324 static void of_fpga_region_notify_post_remove(struct fpga_region *region,
0325 struct of_overlay_notify_data *nd)
0326 {
0327 fpga_bridges_disable(®ion->bridge_list);
0328 fpga_bridges_put(®ion->bridge_list);
0329 fpga_image_info_free(region->info);
0330 region->info = NULL;
0331 }
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344 static int of_fpga_region_notify(struct notifier_block *nb,
0345 unsigned long action, void *arg)
0346 {
0347 struct of_overlay_notify_data *nd = arg;
0348 struct fpga_region *region;
0349 int ret;
0350
0351 switch (action) {
0352 case OF_OVERLAY_PRE_APPLY:
0353 pr_debug("%s OF_OVERLAY_PRE_APPLY\n", __func__);
0354 break;
0355 case OF_OVERLAY_POST_APPLY:
0356 pr_debug("%s OF_OVERLAY_POST_APPLY\n", __func__);
0357 return NOTIFY_OK;
0358 case OF_OVERLAY_PRE_REMOVE:
0359 pr_debug("%s OF_OVERLAY_PRE_REMOVE\n", __func__);
0360 return NOTIFY_OK;
0361 case OF_OVERLAY_POST_REMOVE:
0362 pr_debug("%s OF_OVERLAY_POST_REMOVE\n", __func__);
0363 break;
0364 default:
0365 return NOTIFY_OK;
0366 }
0367
0368 region = of_fpga_region_find(nd->target);
0369 if (!region)
0370 return NOTIFY_OK;
0371
0372 ret = 0;
0373 switch (action) {
0374 case OF_OVERLAY_PRE_APPLY:
0375 ret = of_fpga_region_notify_pre_apply(region, nd);
0376 break;
0377
0378 case OF_OVERLAY_POST_REMOVE:
0379 of_fpga_region_notify_post_remove(region, nd);
0380 break;
0381 }
0382
0383 put_device(®ion->dev);
0384
0385 if (ret)
0386 return notifier_from_errno(ret);
0387
0388 return NOTIFY_OK;
0389 }
0390
0391 static struct notifier_block fpga_region_of_nb = {
0392 .notifier_call = of_fpga_region_notify,
0393 };
0394
0395 static int of_fpga_region_probe(struct platform_device *pdev)
0396 {
0397 struct device *dev = &pdev->dev;
0398 struct device_node *np = dev->of_node;
0399 struct fpga_region *region;
0400 struct fpga_manager *mgr;
0401 int ret;
0402
0403
0404 mgr = of_fpga_region_get_mgr(np);
0405 if (IS_ERR(mgr))
0406 return -EPROBE_DEFER;
0407
0408 region = fpga_region_register(dev, mgr, of_fpga_region_get_bridges);
0409 if (IS_ERR(region)) {
0410 ret = PTR_ERR(region);
0411 goto eprobe_mgr_put;
0412 }
0413
0414 of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev);
0415 platform_set_drvdata(pdev, region);
0416
0417 dev_info(dev, "FPGA Region probed\n");
0418
0419 return 0;
0420
0421 eprobe_mgr_put:
0422 fpga_mgr_put(mgr);
0423 return ret;
0424 }
0425
0426 static int of_fpga_region_remove(struct platform_device *pdev)
0427 {
0428 struct fpga_region *region = platform_get_drvdata(pdev);
0429 struct fpga_manager *mgr = region->mgr;
0430
0431 fpga_region_unregister(region);
0432 fpga_mgr_put(mgr);
0433
0434 return 0;
0435 }
0436
0437 static struct platform_driver of_fpga_region_driver = {
0438 .probe = of_fpga_region_probe,
0439 .remove = of_fpga_region_remove,
0440 .driver = {
0441 .name = "of-fpga-region",
0442 .of_match_table = of_match_ptr(fpga_region_of_match),
0443 },
0444 };
0445
0446
0447
0448
0449
0450
0451
0452 static int __init of_fpga_region_init(void)
0453 {
0454 int ret;
0455
0456 ret = of_overlay_notifier_register(&fpga_region_of_nb);
0457 if (ret)
0458 return ret;
0459
0460 ret = platform_driver_register(&of_fpga_region_driver);
0461 if (ret)
0462 goto err_plat;
0463
0464 return 0;
0465
0466 err_plat:
0467 of_overlay_notifier_unregister(&fpga_region_of_nb);
0468 return ret;
0469 }
0470
0471 static void __exit of_fpga_region_exit(void)
0472 {
0473 platform_driver_unregister(&of_fpga_region_driver);
0474 of_overlay_notifier_unregister(&fpga_region_of_nb);
0475 }
0476
0477 subsys_initcall(of_fpga_region_init);
0478 module_exit(of_fpga_region_exit);
0479
0480 MODULE_DESCRIPTION("FPGA Region");
0481 MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
0482 MODULE_LICENSE("GPL v2");