diff options
Diffstat (limited to 'drivers/fpga/fpga-region.c')
| -rw-r--r-- | drivers/fpga/fpga-region.c | 299 |
1 files changed, 0 insertions, 299 deletions
diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c deleted file mode 100644 index 0d65220d5ec5..000000000000 --- a/drivers/fpga/fpga-region.c +++ /dev/null @@ -1,299 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * FPGA Region - Device Tree support for FPGA programming under Linux - * - * Copyright (C) 2013-2016 Altera Corporation - * Copyright (C) 2017 Intel Corporation - */ -#include <linux/fpga/fpga-bridge.h> -#include <linux/fpga/fpga-mgr.h> -#include <linux/fpga/fpga-region.h> -#include <linux/idr.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/spinlock.h> - -static DEFINE_IDA(fpga_region_ida); -static struct class *fpga_region_class; - -struct fpga_region *fpga_region_class_find( - struct device *start, const void *data, - int (*match)(struct device *, const void *)) -{ - struct device *dev; - - dev = class_find_device(fpga_region_class, start, data, match); - if (!dev) - return NULL; - - return to_fpga_region(dev); -} -EXPORT_SYMBOL_GPL(fpga_region_class_find); - -/** - * fpga_region_get - get an exclusive reference to a fpga region - * @region: FPGA Region struct - * - * Caller should call fpga_region_put() when done with region. - * - * Return fpga_region struct if successful. - * Return -EBUSY if someone already has a reference to the region. - * Return -ENODEV if @np is not a FPGA Region. - */ -static struct fpga_region *fpga_region_get(struct fpga_region *region) -{ - struct device *dev = ®ion->dev; - - if (!mutex_trylock(®ion->mutex)) { - dev_dbg(dev, "%s: FPGA Region already in use\n", __func__); - return ERR_PTR(-EBUSY); - } - - get_device(dev); - if (!try_module_get(dev->parent->driver->owner)) { - put_device(dev); - mutex_unlock(®ion->mutex); - return ERR_PTR(-ENODEV); - } - - dev_dbg(dev, "get\n"); - - return region; -} - -/** - * fpga_region_put - release a reference to a region - * - * @region: FPGA region - */ -static void fpga_region_put(struct fpga_region *region) -{ - struct device *dev = ®ion->dev; - - dev_dbg(dev, "put\n"); - - module_put(dev->parent->driver->owner); - put_device(dev); - mutex_unlock(®ion->mutex); -} - -/** - * fpga_region_program_fpga - program FPGA - * - * @region: FPGA region - * - * Program an FPGA using fpga image info (region->info). - * If the region has a get_bridges function, the exclusive reference for the - * bridges will be held if programming succeeds. This is intended to prevent - * reprogramming the region until the caller considers it safe to do so. - * The caller will need to call fpga_bridges_put() before attempting to - * reprogram the region. - * - * Return 0 for success or negative error code. - */ -int fpga_region_program_fpga(struct fpga_region *region) -{ - struct device *dev = ®ion->dev; - struct fpga_image_info *info = region->info; - int ret; - - region = fpga_region_get(region); - if (IS_ERR(region)) { - dev_err(dev, "failed to get FPGA region\n"); - return PTR_ERR(region); - } - - ret = fpga_mgr_lock(region->mgr); - if (ret) { - dev_err(dev, "FPGA manager is busy\n"); - goto err_put_region; - } - - /* - * In some cases, we already have a list of bridges in the - * fpga region struct. Or we don't have any bridges. - */ - if (region->get_bridges) { - ret = region->get_bridges(region); - if (ret) { - dev_err(dev, "failed to get fpga region bridges\n"); - goto err_unlock_mgr; - } - } - - ret = fpga_bridges_disable(®ion->bridge_list); - if (ret) { - dev_err(dev, "failed to disable bridges\n"); - goto err_put_br; - } - - ret = fpga_mgr_load(region->mgr, info); - if (ret) { - dev_err(dev, "failed to load FPGA image\n"); - goto err_put_br; - } - - ret = fpga_bridges_enable(®ion->bridge_list); - if (ret) { - dev_err(dev, "failed to enable region bridges\n"); - goto err_put_br; - } - - fpga_mgr_unlock(region->mgr); - fpga_region_put(region); - - return 0; - -err_put_br: - if (region->get_bridges) - fpga_bridges_put(®ion->bridge_list); -err_unlock_mgr: - fpga_mgr_unlock(region->mgr); -err_put_region: - fpga_region_put(region); - - return ret; -} -EXPORT_SYMBOL_GPL(fpga_region_program_fpga); - -static ssize_t compat_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fpga_region *region = to_fpga_region(dev); - - if (!region->compat_id) - return -ENOENT; - - return sprintf(buf, "%016llx%016llx\n", - (unsigned long long)region->compat_id->id_h, - (unsigned long long)region->compat_id->id_l); -} - -static DEVICE_ATTR_RO(compat_id); - -static struct attribute *fpga_region_attrs[] = { - &dev_attr_compat_id.attr, - NULL, -}; -ATTRIBUTE_GROUPS(fpga_region); - -/** - * fpga_region_create - alloc and init a struct fpga_region - * @dev: device parent - * @mgr: manager that programs this region - * @get_bridges: optional function to get bridges to a list - * - * Return: struct fpga_region or NULL - */ -struct fpga_region -*fpga_region_create(struct device *dev, - struct fpga_manager *mgr, - int (*get_bridges)(struct fpga_region *)) -{ - struct fpga_region *region; - int id, ret = 0; - - region = kzalloc(sizeof(*region), GFP_KERNEL); - if (!region) - return NULL; - - id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); - if (id < 0) - goto err_free; - - region->mgr = mgr; - region->get_bridges = get_bridges; - mutex_init(®ion->mutex); - INIT_LIST_HEAD(®ion->bridge_list); - - device_initialize(®ion->dev); - region->dev.class = fpga_region_class; - region->dev.parent = dev; - region->dev.of_node = dev->of_node; - region->dev.id = id; - - ret = dev_set_name(®ion->dev, "region%d", id); - if (ret) - goto err_remove; - - return region; - -err_remove: - ida_simple_remove(&fpga_region_ida, id); -err_free: - kfree(region); - - return NULL; -} -EXPORT_SYMBOL_GPL(fpga_region_create); - -/** - * fpga_region_free - free a struct fpga_region - * @region: FPGA region created by fpga_region_create - */ -void fpga_region_free(struct fpga_region *region) -{ - ida_simple_remove(&fpga_region_ida, region->dev.id); - kfree(region); -} -EXPORT_SYMBOL_GPL(fpga_region_free); - -/** - * fpga_region_register - register a FPGA region - * @region: FPGA region created by fpga_region_create - * Return: 0 or -errno - */ -int fpga_region_register(struct fpga_region *region) -{ - return device_add(®ion->dev); - -} -EXPORT_SYMBOL_GPL(fpga_region_register); - -/** - * fpga_region_unregister - unregister and free a FPGA region - * @region: FPGA region - */ -void fpga_region_unregister(struct fpga_region *region) -{ - device_unregister(®ion->dev); -} -EXPORT_SYMBOL_GPL(fpga_region_unregister); - -static void fpga_region_dev_release(struct device *dev) -{ - struct fpga_region *region = to_fpga_region(dev); - - fpga_region_free(region); -} - -/** - * fpga_region_init - init function for fpga_region class - * Creates the fpga_region class and registers a reconfig notifier. - */ -static int __init fpga_region_init(void) -{ - fpga_region_class = class_create(THIS_MODULE, "fpga_region"); - if (IS_ERR(fpga_region_class)) - return PTR_ERR(fpga_region_class); - - fpga_region_class->dev_groups = fpga_region_groups; - fpga_region_class->dev_release = fpga_region_dev_release; - - return 0; -} - -static void __exit fpga_region_exit(void) -{ - class_destroy(fpga_region_class); - ida_destroy(&fpga_region_ida); -} - -subsys_initcall(fpga_region_init); -module_exit(fpga_region_exit); - -MODULE_DESCRIPTION("FPGA Region"); -MODULE_AUTHOR("Alan Tull <atull@kernel.org>"); -MODULE_LICENSE("GPL v2"); |
