^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * FPGA Region - Support for FPGA programming under Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2013-2016 Altera Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2017 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/fpga/fpga-bridge.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/fpga/fpga-mgr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/fpga/fpga-region.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static DEFINE_IDA(fpga_region_ida);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static struct class *fpga_region_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct fpga_region *fpga_region_class_find(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct device *start, const void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) int (*match)(struct device *, const void *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) dev = class_find_device(fpga_region_class, start, data, match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return to_fpga_region(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) EXPORT_SYMBOL_GPL(fpga_region_class_find);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * fpga_region_get - get an exclusive reference to a fpga region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * @region: FPGA Region struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Caller should call fpga_region_put() when done with region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Return fpga_region struct if successful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Return -EBUSY if someone already has a reference to the region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Return -ENODEV if @np is not a FPGA Region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static struct fpga_region *fpga_region_get(struct fpga_region *region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct device *dev = ®ion->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (!mutex_trylock(®ion->mutex)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) dev_dbg(dev, "%s: FPGA Region already in use\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return ERR_PTR(-EBUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) get_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (!try_module_get(dev->parent->driver->owner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) put_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) mutex_unlock(®ion->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) dev_dbg(dev, "get\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * fpga_region_put - release a reference to a region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * @region: FPGA region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void fpga_region_put(struct fpga_region *region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct device *dev = ®ion->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) dev_dbg(dev, "put\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) module_put(dev->parent->driver->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) put_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) mutex_unlock(®ion->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * fpga_region_program_fpga - program FPGA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @region: FPGA region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Program an FPGA using fpga image info (region->info).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * If the region has a get_bridges function, the exclusive reference for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * bridges will be held if programming succeeds. This is intended to prevent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * reprogramming the region until the caller considers it safe to do so.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * The caller will need to call fpga_bridges_put() before attempting to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * reprogram the region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Return 0 for success or negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int fpga_region_program_fpga(struct fpga_region *region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct device *dev = ®ion->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct fpga_image_info *info = region->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) region = fpga_region_get(region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (IS_ERR(region)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) dev_err(dev, "failed to get FPGA region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return PTR_ERR(region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ret = fpga_mgr_lock(region->mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dev_err(dev, "FPGA manager is busy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) goto err_put_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * In some cases, we already have a list of bridges in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * fpga region struct. Or we don't have any bridges.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (region->get_bridges) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ret = region->get_bridges(region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dev_err(dev, "failed to get fpga region bridges\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) goto err_unlock_mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ret = fpga_bridges_disable(®ion->bridge_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dev_err(dev, "failed to disable bridges\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) goto err_put_br;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ret = fpga_mgr_load(region->mgr, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) dev_err(dev, "failed to load FPGA image\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) goto err_put_br;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ret = fpga_bridges_enable(®ion->bridge_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) dev_err(dev, "failed to enable region bridges\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) goto err_put_br;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) fpga_mgr_unlock(region->mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) fpga_region_put(region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) err_put_br:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (region->get_bridges)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) fpga_bridges_put(®ion->bridge_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) err_unlock_mgr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) fpga_mgr_unlock(region->mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) err_put_region:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) fpga_region_put(region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) EXPORT_SYMBOL_GPL(fpga_region_program_fpga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static ssize_t compat_id_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct fpga_region *region = to_fpga_region(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (!region->compat_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return sprintf(buf, "%016llx%016llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) (unsigned long long)region->compat_id->id_h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) (unsigned long long)region->compat_id->id_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static DEVICE_ATTR_RO(compat_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct attribute *fpga_region_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) &dev_attr_compat_id.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ATTRIBUTE_GROUPS(fpga_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * fpga_region_create - alloc and init a struct fpga_region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * @dev: device parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * @mgr: manager that programs this region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * @get_bridges: optional function to get bridges to a list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * The caller of this function is responsible for freeing the resulting region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * struct with fpga_region_free(). Using devm_fpga_region_create() instead is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * recommended.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * Return: struct fpga_region or NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct fpga_region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *fpga_region_create(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct fpga_manager *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int (*get_bridges)(struct fpga_region *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct fpga_region *region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int id, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) region = kzalloc(sizeof(*region), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (id < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) region->mgr = mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) region->get_bridges = get_bridges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) mutex_init(®ion->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) INIT_LIST_HEAD(®ion->bridge_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) device_initialize(®ion->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) region->dev.class = fpga_region_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) region->dev.parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) region->dev.of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) region->dev.id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ret = dev_set_name(®ion->dev, "region%d", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) goto err_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) err_remove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ida_simple_remove(&fpga_region_ida, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) kfree(region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) EXPORT_SYMBOL_GPL(fpga_region_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * fpga_region_free - free a FPGA region created by fpga_region_create()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * @region: FPGA region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) void fpga_region_free(struct fpga_region *region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ida_simple_remove(&fpga_region_ida, region->dev.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) kfree(region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) EXPORT_SYMBOL_GPL(fpga_region_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static void devm_fpga_region_release(struct device *dev, void *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct fpga_region *region = *(struct fpga_region **)res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) fpga_region_free(region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * devm_fpga_region_create - create and initialize a managed FPGA region struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * @dev: device parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * @mgr: manager that programs this region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * @get_bridges: optional function to get bridges to a list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * This function is intended for use in a FPGA region driver's probe function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * After the region driver creates the region struct with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * devm_fpga_region_create(), it should register it with fpga_region_register().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * The region driver's remove function should call fpga_region_unregister().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * The region struct allocated with this function will be freed automatically on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * driver detach. This includes the case of a probe function returning error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * before calling fpga_region_register(), the struct will still get cleaned up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Return: struct fpga_region or NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct fpga_region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) *devm_fpga_region_create(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct fpga_manager *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) int (*get_bridges)(struct fpga_region *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct fpga_region **ptr, *region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) region = fpga_region_create(dev, mgr, get_bridges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (!region) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) devres_free(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) *ptr = region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) devres_add(dev, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) EXPORT_SYMBOL_GPL(devm_fpga_region_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * fpga_region_register - register a FPGA region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * @region: FPGA region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * Return: 0 or -errno
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) int fpga_region_register(struct fpga_region *region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return device_add(®ion->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) EXPORT_SYMBOL_GPL(fpga_region_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * fpga_region_unregister - unregister a FPGA region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * @region: FPGA region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * This function is intended for use in a FPGA region driver's remove function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) void fpga_region_unregister(struct fpga_region *region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) device_unregister(®ion->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) EXPORT_SYMBOL_GPL(fpga_region_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static void fpga_region_dev_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * fpga_region_init - init function for fpga_region class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * Creates the fpga_region class and registers a reconfig notifier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int __init fpga_region_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) fpga_region_class = class_create(THIS_MODULE, "fpga_region");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (IS_ERR(fpga_region_class))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return PTR_ERR(fpga_region_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) fpga_region_class->dev_groups = fpga_region_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) fpga_region_class->dev_release = fpga_region_dev_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static void __exit fpga_region_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) class_destroy(fpga_region_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) ida_destroy(&fpga_region_ida);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) subsys_initcall(fpga_region_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) module_exit(fpga_region_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MODULE_DESCRIPTION("FPGA Region");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) MODULE_LICENSE("GPL v2");