aboutsummaryrefslogtreecommitdiff
path: root/drivers/fpga/fpga-region.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/fpga/fpga-region.c')
-rw-r--r--drivers/fpga/fpga-region.c299
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 = &region->dev;
-
- if (!mutex_trylock(&region->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(&region->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 = &region->dev;
-
- dev_dbg(dev, "put\n");
-
- module_put(dev->parent->driver->owner);
- put_device(dev);
- mutex_unlock(&region->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 = &region->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(&region->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(&region->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(&region->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(&region->mutex);
- INIT_LIST_HEAD(&region->bridge_list);
-
- device_initialize(&region->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(&region->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(&region->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(&region->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");