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/slab.h>
0016 #include <linux/spinlock.h>
0017
0018 static DEFINE_IDA(fpga_region_ida);
0019 static struct class *fpga_region_class;
0020
0021 struct fpga_region *
0022 fpga_region_class_find(struct device *start, const void *data,
0023 int (*match)(struct device *, const void *))
0024 {
0025 struct device *dev;
0026
0027 dev = class_find_device(fpga_region_class, start, data, match);
0028 if (!dev)
0029 return NULL;
0030
0031 return to_fpga_region(dev);
0032 }
0033 EXPORT_SYMBOL_GPL(fpga_region_class_find);
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 static struct fpga_region *fpga_region_get(struct fpga_region *region)
0046 {
0047 struct device *dev = ®ion->dev;
0048
0049 if (!mutex_trylock(®ion->mutex)) {
0050 dev_dbg(dev, "%s: FPGA Region already in use\n", __func__);
0051 return ERR_PTR(-EBUSY);
0052 }
0053
0054 get_device(dev);
0055 if (!try_module_get(dev->parent->driver->owner)) {
0056 put_device(dev);
0057 mutex_unlock(®ion->mutex);
0058 return ERR_PTR(-ENODEV);
0059 }
0060
0061 dev_dbg(dev, "get\n");
0062
0063 return region;
0064 }
0065
0066
0067
0068
0069
0070
0071 static void fpga_region_put(struct fpga_region *region)
0072 {
0073 struct device *dev = ®ion->dev;
0074
0075 dev_dbg(dev, "put\n");
0076
0077 module_put(dev->parent->driver->owner);
0078 put_device(dev);
0079 mutex_unlock(®ion->mutex);
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 int fpga_region_program_fpga(struct fpga_region *region)
0097 {
0098 struct device *dev = ®ion->dev;
0099 struct fpga_image_info *info = region->info;
0100 int ret;
0101
0102 region = fpga_region_get(region);
0103 if (IS_ERR(region)) {
0104 dev_err(dev, "failed to get FPGA region\n");
0105 return PTR_ERR(region);
0106 }
0107
0108 ret = fpga_mgr_lock(region->mgr);
0109 if (ret) {
0110 dev_err(dev, "FPGA manager is busy\n");
0111 goto err_put_region;
0112 }
0113
0114
0115
0116
0117
0118 if (region->get_bridges) {
0119 ret = region->get_bridges(region);
0120 if (ret) {
0121 dev_err(dev, "failed to get fpga region bridges\n");
0122 goto err_unlock_mgr;
0123 }
0124 }
0125
0126 ret = fpga_bridges_disable(®ion->bridge_list);
0127 if (ret) {
0128 dev_err(dev, "failed to disable bridges\n");
0129 goto err_put_br;
0130 }
0131
0132 ret = fpga_mgr_load(region->mgr, info);
0133 if (ret) {
0134 dev_err(dev, "failed to load FPGA image\n");
0135 goto err_put_br;
0136 }
0137
0138 ret = fpga_bridges_enable(®ion->bridge_list);
0139 if (ret) {
0140 dev_err(dev, "failed to enable region bridges\n");
0141 goto err_put_br;
0142 }
0143
0144 fpga_mgr_unlock(region->mgr);
0145 fpga_region_put(region);
0146
0147 return 0;
0148
0149 err_put_br:
0150 if (region->get_bridges)
0151 fpga_bridges_put(®ion->bridge_list);
0152 err_unlock_mgr:
0153 fpga_mgr_unlock(region->mgr);
0154 err_put_region:
0155 fpga_region_put(region);
0156
0157 return ret;
0158 }
0159 EXPORT_SYMBOL_GPL(fpga_region_program_fpga);
0160
0161 static ssize_t compat_id_show(struct device *dev,
0162 struct device_attribute *attr, char *buf)
0163 {
0164 struct fpga_region *region = to_fpga_region(dev);
0165
0166 if (!region->compat_id)
0167 return -ENOENT;
0168
0169 return sprintf(buf, "%016llx%016llx\n",
0170 (unsigned long long)region->compat_id->id_h,
0171 (unsigned long long)region->compat_id->id_l);
0172 }
0173
0174 static DEVICE_ATTR_RO(compat_id);
0175
0176 static struct attribute *fpga_region_attrs[] = {
0177 &dev_attr_compat_id.attr,
0178 NULL,
0179 };
0180 ATTRIBUTE_GROUPS(fpga_region);
0181
0182
0183
0184
0185
0186
0187
0188
0189 struct fpga_region *
0190 fpga_region_register_full(struct device *parent, const struct fpga_region_info *info)
0191 {
0192 struct fpga_region *region;
0193 int id, ret = 0;
0194
0195 if (!info) {
0196 dev_err(parent,
0197 "Attempt to register without required info structure\n");
0198 return ERR_PTR(-EINVAL);
0199 }
0200
0201 region = kzalloc(sizeof(*region), GFP_KERNEL);
0202 if (!region)
0203 return ERR_PTR(-ENOMEM);
0204
0205 id = ida_alloc(&fpga_region_ida, GFP_KERNEL);
0206 if (id < 0) {
0207 ret = id;
0208 goto err_free;
0209 }
0210
0211 region->mgr = info->mgr;
0212 region->compat_id = info->compat_id;
0213 region->priv = info->priv;
0214 region->get_bridges = info->get_bridges;
0215
0216 mutex_init(®ion->mutex);
0217 INIT_LIST_HEAD(®ion->bridge_list);
0218
0219 region->dev.class = fpga_region_class;
0220 region->dev.parent = parent;
0221 region->dev.of_node = parent->of_node;
0222 region->dev.id = id;
0223
0224 ret = dev_set_name(®ion->dev, "region%d", id);
0225 if (ret)
0226 goto err_remove;
0227
0228 ret = device_register(®ion->dev);
0229 if (ret) {
0230 put_device(®ion->dev);
0231 return ERR_PTR(ret);
0232 }
0233
0234 return region;
0235
0236 err_remove:
0237 ida_free(&fpga_region_ida, id);
0238 err_free:
0239 kfree(region);
0240
0241 return ERR_PTR(ret);
0242 }
0243 EXPORT_SYMBOL_GPL(fpga_region_register_full);
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 struct fpga_region *
0258 fpga_region_register(struct device *parent, struct fpga_manager *mgr,
0259 int (*get_bridges)(struct fpga_region *))
0260 {
0261 struct fpga_region_info info = { 0 };
0262
0263 info.mgr = mgr;
0264 info.get_bridges = get_bridges;
0265
0266 return fpga_region_register_full(parent, &info);
0267 }
0268 EXPORT_SYMBOL_GPL(fpga_region_register);
0269
0270
0271
0272
0273
0274
0275
0276 void fpga_region_unregister(struct fpga_region *region)
0277 {
0278 device_unregister(®ion->dev);
0279 }
0280 EXPORT_SYMBOL_GPL(fpga_region_unregister);
0281
0282 static void fpga_region_dev_release(struct device *dev)
0283 {
0284 struct fpga_region *region = to_fpga_region(dev);
0285
0286 ida_free(&fpga_region_ida, region->dev.id);
0287 kfree(region);
0288 }
0289
0290
0291
0292
0293
0294 static int __init fpga_region_init(void)
0295 {
0296 fpga_region_class = class_create(THIS_MODULE, "fpga_region");
0297 if (IS_ERR(fpga_region_class))
0298 return PTR_ERR(fpga_region_class);
0299
0300 fpga_region_class->dev_groups = fpga_region_groups;
0301 fpga_region_class->dev_release = fpga_region_dev_release;
0302
0303 return 0;
0304 }
0305
0306 static void __exit fpga_region_exit(void)
0307 {
0308 class_destroy(fpga_region_class);
0309 ida_destroy(&fpga_region_ida);
0310 }
0311
0312 subsys_initcall(fpga_region_init);
0313 module_exit(fpga_region_exit);
0314
0315 MODULE_DESCRIPTION("FPGA Region");
0316 MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
0317 MODULE_LICENSE("GPL v2");