diff options
author | Alan Tull <atull@kernel.org> | 2017-11-15 15:20:20 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-11-28 10:30:37 -0500 |
commit | c8898eda81e0b949ca214e1a45ce1b56677eb849 (patch) | |
tree | 448d586adecd41d97ba4d2a2f1163f7979f781fe /drivers/fpga/fpga-region.c | |
parent | 61c32102391ff38dfd4aba835dd0f99db6b46908 (diff) |
fpga: region: separate out code that parses the overlay
New function of_fpga_region_parse_ov added, moving code
from fpga_region_notify_pre_apply. This function
gets the FPGA image info from the overlay and is able
to simplify some of the logic involved.
This is a baby step in refactoring the FPGA region code to
separate out common code from Device Tree overlay support.
Signed-off-by: Alan Tull <atull@kernel.org>
Acked-by: Moritz Fischer <mdf@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/fpga/fpga-region.c')
-rw-r--r-- | drivers/fpga/fpga-region.c | 122 |
1 files changed, 73 insertions, 49 deletions
diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index eaacf5049381..2a8621db5f5b 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c | |||
@@ -321,33 +321,22 @@ static int child_regions_with_firmware(struct device_node *overlay) | |||
321 | } | 321 | } |
322 | 322 | ||
323 | /** | 323 | /** |
324 | * fpga_region_notify_pre_apply - pre-apply overlay notification | 324 | * of_fpga_region_parse_ov - parse and check overlay applied to region |
325 | * | ||
326 | * @region: FPGA region that the overlay was applied to | ||
327 | * @nd: overlay notification data | ||
328 | * | ||
329 | * Called after when an overlay targeted to a FPGA Region is about to be | ||
330 | * applied. Function will check the properties that will be added to the FPGA | ||
331 | * region. If the checks pass, it will program the FPGA. | ||
332 | * | ||
333 | * The checks are: | ||
334 | * The overlay must add either firmware-name or external-fpga-config property | ||
335 | * to the FPGA Region. | ||
336 | * | ||
337 | * firmware-name : program the FPGA | ||
338 | * external-fpga-config : FPGA is already programmed | ||
339 | * encrypted-fpga-config : FPGA bitstream is encrypted | ||
340 | * | 325 | * |
341 | * The overlay can add other FPGA regions, but child FPGA regions cannot have a | 326 | * @region: FPGA region |
342 | * firmware-name property since those regions don't exist yet. | 327 | * @overlay: overlay applied to the FPGA region |
343 | * | 328 | * |
344 | * If the overlay that breaks the rules, notifier returns an error and the | 329 | * Given an overlay applied to a FPGA region, parse the FPGA image specific |
345 | * overlay is rejected before it goes into the main tree. | 330 | * info in the overlay and do some checking. |
346 | * | 331 | * |
347 | * Returns 0 for success or negative error code for failure. | 332 | * Returns: |
333 | * NULL if overlay doesn't direct us to program the FPGA. | ||
334 | * fpga_image_info struct if there is an image to program. | ||
335 | * error code for invalid overlay. | ||
348 | */ | 336 | */ |
349 | static int fpga_region_notify_pre_apply(struct fpga_region *region, | 337 | static struct fpga_image_info *of_fpga_region_parse_ov( |
350 | struct of_overlay_notify_data *nd) | 338 | struct fpga_region *region, |
339 | struct device_node *overlay) | ||
351 | { | 340 | { |
352 | struct device *dev = ®ion->dev; | 341 | struct device *dev = ®ion->dev; |
353 | struct fpga_image_info *info; | 342 | struct fpga_image_info *info; |
@@ -356,7 +345,7 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, | |||
356 | 345 | ||
357 | if (region->info) { | 346 | if (region->info) { |
358 | dev_err(dev, "Region already has overlay applied.\n"); | 347 | dev_err(dev, "Region already has overlay applied.\n"); |
359 | return -EINVAL; | 348 | return ERR_PTR(-EINVAL); |
360 | } | 349 | } |
361 | 350 | ||
362 | /* | 351 | /* |
@@ -364,67 +353,102 @@ static int fpga_region_notify_pre_apply(struct fpga_region *region, | |||
364 | * firmware-name property (would mean that an FPGA region that has | 353 | * firmware-name property (would mean that an FPGA region that has |
365 | * not been added to the live tree yet is doing FPGA programming). | 354 | * not been added to the live tree yet is doing FPGA programming). |
366 | */ | 355 | */ |
367 | ret = child_regions_with_firmware(nd->overlay); | 356 | ret = child_regions_with_firmware(overlay); |
368 | if (ret) | 357 | if (ret) |
369 | return ret; | 358 | return ERR_PTR(ret); |
370 | 359 | ||
371 | info = fpga_image_info_alloc(dev); | 360 | info = fpga_image_info_alloc(dev); |
372 | if (!info) | 361 | if (!info) |
373 | return -ENOMEM; | 362 | return ERR_PTR(-ENOMEM); |
374 | 363 | ||
375 | info->overlay = nd->overlay; | 364 | info->overlay = overlay; |
376 | 365 | ||
377 | /* Read FPGA region properties from the overlay */ | 366 | /* Read FPGA region properties from the overlay */ |
378 | if (of_property_read_bool(nd->overlay, "partial-fpga-config")) | 367 | if (of_property_read_bool(overlay, "partial-fpga-config")) |
379 | info->flags |= FPGA_MGR_PARTIAL_RECONFIG; | 368 | info->flags |= FPGA_MGR_PARTIAL_RECONFIG; |
380 | 369 | ||
381 | if (of_property_read_bool(nd->overlay, "external-fpga-config")) | 370 | if (of_property_read_bool(overlay, "external-fpga-config")) |
382 | info->flags |= FPGA_MGR_EXTERNAL_CONFIG; | 371 | info->flags |= FPGA_MGR_EXTERNAL_CONFIG; |
383 | 372 | ||
384 | if (of_property_read_bool(nd->overlay, "encrypted-fpga-config")) | 373 | if (of_property_read_bool(overlay, "encrypted-fpga-config")) |
385 | info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM; | 374 | info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM; |
386 | 375 | ||
387 | if (!of_property_read_string(nd->overlay, "firmware-name", | 376 | if (!of_property_read_string(overlay, "firmware-name", |
388 | &firmware_name)) { | 377 | &firmware_name)) { |
389 | info->firmware_name = devm_kstrdup(dev, firmware_name, | 378 | info->firmware_name = devm_kstrdup(dev, firmware_name, |
390 | GFP_KERNEL); | 379 | GFP_KERNEL); |
391 | if (!info->firmware_name) | 380 | if (!info->firmware_name) |
392 | return -ENOMEM; | 381 | return ERR_PTR(-ENOMEM); |
393 | } | 382 | } |
394 | 383 | ||
395 | of_property_read_u32(nd->overlay, "region-unfreeze-timeout-us", | 384 | of_property_read_u32(overlay, "region-unfreeze-timeout-us", |
396 | &info->enable_timeout_us); | 385 | &info->enable_timeout_us); |
397 | 386 | ||
398 | of_property_read_u32(nd->overlay, "region-freeze-timeout-us", | 387 | of_property_read_u32(overlay, "region-freeze-timeout-us", |
399 | &info->disable_timeout_us); | 388 | &info->disable_timeout_us); |
400 | 389 | ||
401 | of_property_read_u32(nd->overlay, "config-complete-timeout-us", | 390 | of_property_read_u32(overlay, "config-complete-timeout-us", |
402 | &info->config_complete_timeout_us); | 391 | &info->config_complete_timeout_us); |
403 | 392 | ||
404 | /* If FPGA was externally programmed, don't specify firmware */ | 393 | /* If overlay is not programming the FPGA, don't need FPGA image info */ |
405 | if ((info->flags & FPGA_MGR_EXTERNAL_CONFIG) && info->firmware_name) { | 394 | if (!info->firmware_name) { |
406 | dev_err(dev, "error: specified firmware and external-fpga-config"); | 395 | ret = 0; |
407 | fpga_image_info_free(info); | 396 | goto ret_no_info; |
408 | return -EINVAL; | ||
409 | } | 397 | } |
410 | 398 | ||
411 | /* FPGA is already configured externally. We're done. */ | 399 | /* |
400 | * If overlay informs us FPGA was externally programmed, specifying | ||
401 | * firmware here would be ambiguous. | ||
402 | */ | ||
412 | if (info->flags & FPGA_MGR_EXTERNAL_CONFIG) { | 403 | if (info->flags & FPGA_MGR_EXTERNAL_CONFIG) { |
413 | fpga_image_info_free(info); | 404 | dev_err(dev, "error: specified firmware and external-fpga-config"); |
414 | return 0; | 405 | ret = -EINVAL; |
406 | goto ret_no_info; | ||
415 | } | 407 | } |
416 | 408 | ||
417 | /* If we got this far, we should be programming the FPGA */ | 409 | return info; |
418 | if (!info->firmware_name) { | 410 | ret_no_info: |
419 | dev_err(dev, "should specify firmware-name or external-fpga-config\n"); | 411 | fpga_image_info_free(info); |
420 | fpga_image_info_free(info); | 412 | return ERR_PTR(ret); |
413 | } | ||
414 | |||
415 | /** | ||
416 | * fpga_region_notify_pre_apply - pre-apply overlay notification | ||
417 | * | ||
418 | * @region: FPGA region that the overlay was applied to | ||
419 | * @nd: overlay notification data | ||
420 | * | ||
421 | * Called when an overlay targeted to a FPGA Region is about to be applied. | ||
422 | * Parses the overlay for properties that influence how the FPGA will be | ||
423 | * programmed and does some checking. If the checks pass, programs the FPGA. | ||
424 | * If the checks fail, overlay is rejected and does not get added to the | ||
425 | * live tree. | ||
426 | * | ||
427 | * Returns 0 for success or negative error code for failure. | ||
428 | */ | ||
429 | static int fpga_region_notify_pre_apply(struct fpga_region *region, | ||
430 | struct of_overlay_notify_data *nd) | ||
431 | { | ||
432 | struct device *dev = ®ion->dev; | ||
433 | struct fpga_image_info *info; | ||
434 | int ret; | ||
435 | |||
436 | if (region->info) { | ||
437 | dev_err(dev, "Region already has overlay applied.\n"); | ||
421 | return -EINVAL; | 438 | return -EINVAL; |
422 | } | 439 | } |
423 | 440 | ||
424 | region->info = info; | 441 | info = of_fpga_region_parse_ov(region, nd->overlay); |
442 | if (IS_ERR(info)) | ||
443 | return PTR_ERR(info); | ||
444 | |||
445 | if (!info) | ||
446 | return 0; | ||
425 | 447 | ||
448 | region->info = info; | ||
426 | ret = fpga_region_program_fpga(region); | 449 | ret = fpga_region_program_fpga(region); |
427 | if (ret) { | 450 | if (ret) { |
451 | /* error; reject overlay */ | ||
428 | fpga_image_info_free(info); | 452 | fpga_image_info_free(info); |
429 | region->info = NULL; | 453 | region->info = NULL; |
430 | } | 454 | } |