1 // SPDX-License-Identifier: GPL-2.0
3 * FPGA Region - Support for FPGA programming under Linux
5 * Copyright (C) 2013-2016 Altera Corporation
6 * Copyright (C) 2017 Intel Corporation
8 #include <linux/fpga/fpga-bridge.h>
9 #include <linux/fpga/fpga-mgr.h>
10 #include <linux/fpga/fpga-region.h>
11 #include <linux/idr.h>
12 #include <linux/kernel.h>
13 #include <linux/list.h>
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/spinlock.h>
18 static DEFINE_IDA(fpga_region_ida
);
19 static const struct class fpga_region_class
;
22 fpga_region_class_find(struct device
*start
, const void *data
,
23 int (*match
)(struct device
*, const void *))
27 dev
= class_find_device(&fpga_region_class
, start
, data
, match
);
31 return to_fpga_region(dev
);
33 EXPORT_SYMBOL_GPL(fpga_region_class_find
);
36 * fpga_region_get - get an exclusive reference to an fpga region
37 * @region: FPGA Region struct
39 * Caller should call fpga_region_put() when done with region.
42 * * fpga_region struct if successful.
43 * * -EBUSY if someone already has a reference to the region.
44 * * -ENODEV if can't take parent driver module refcount.
46 static struct fpga_region
*fpga_region_get(struct fpga_region
*region
)
48 struct device
*dev
= ®ion
->dev
;
50 if (!mutex_trylock(®ion
->mutex
)) {
51 dev_dbg(dev
, "%s: FPGA Region already in use\n", __func__
);
52 return ERR_PTR(-EBUSY
);
56 if (!try_module_get(region
->ops_owner
)) {
58 mutex_unlock(®ion
->mutex
);
59 return ERR_PTR(-ENODEV
);
62 dev_dbg(dev
, "get\n");
68 * fpga_region_put - release a reference to a region
70 * @region: FPGA region
72 static void fpga_region_put(struct fpga_region
*region
)
74 struct device
*dev
= ®ion
->dev
;
76 dev_dbg(dev
, "put\n");
78 module_put(region
->ops_owner
);
80 mutex_unlock(®ion
->mutex
);
84 * fpga_region_program_fpga - program FPGA
86 * @region: FPGA region
88 * Program an FPGA using fpga image info (region->info).
89 * If the region has a get_bridges function, the exclusive reference for the
90 * bridges will be held if programming succeeds. This is intended to prevent
91 * reprogramming the region until the caller considers it safe to do so.
92 * The caller will need to call fpga_bridges_put() before attempting to
93 * reprogram the region.
95 * Return: 0 for success or negative error code.
97 int fpga_region_program_fpga(struct fpga_region
*region
)
99 struct device
*dev
= ®ion
->dev
;
100 struct fpga_image_info
*info
= region
->info
;
103 region
= fpga_region_get(region
);
104 if (IS_ERR(region
)) {
105 dev_err(dev
, "failed to get FPGA region\n");
106 return PTR_ERR(region
);
109 ret
= fpga_mgr_lock(region
->mgr
);
111 dev_err(dev
, "FPGA manager is busy\n");
116 * In some cases, we already have a list of bridges in the
117 * fpga region struct. Or we don't have any bridges.
119 if (region
->get_bridges
) {
120 ret
= region
->get_bridges(region
);
122 dev_err(dev
, "failed to get fpga region bridges\n");
127 ret
= fpga_bridges_disable(®ion
->bridge_list
);
129 dev_err(dev
, "failed to disable bridges\n");
133 ret
= fpga_mgr_load(region
->mgr
, info
);
135 dev_err(dev
, "failed to load FPGA image\n");
139 ret
= fpga_bridges_enable(®ion
->bridge_list
);
141 dev_err(dev
, "failed to enable region bridges\n");
145 fpga_mgr_unlock(region
->mgr
);
146 fpga_region_put(region
);
151 if (region
->get_bridges
)
152 fpga_bridges_put(®ion
->bridge_list
);
154 fpga_mgr_unlock(region
->mgr
);
156 fpga_region_put(region
);
160 EXPORT_SYMBOL_GPL(fpga_region_program_fpga
);
162 static ssize_t
compat_id_show(struct device
*dev
,
163 struct device_attribute
*attr
, char *buf
)
165 struct fpga_region
*region
= to_fpga_region(dev
);
167 if (!region
->compat_id
)
170 return sprintf(buf
, "%016llx%016llx\n",
171 (unsigned long long)region
->compat_id
->id_h
,
172 (unsigned long long)region
->compat_id
->id_l
);
175 static DEVICE_ATTR_RO(compat_id
);
177 static struct attribute
*fpga_region_attrs
[] = {
178 &dev_attr_compat_id
.attr
,
181 ATTRIBUTE_GROUPS(fpga_region
);
184 * __fpga_region_register_full - create and register an FPGA Region device
185 * @parent: device parent
186 * @info: parameters for FPGA Region
187 * @owner: module containing the get_bridges function
189 * Return: struct fpga_region or ERR_PTR()
192 __fpga_region_register_full(struct device
*parent
, const struct fpga_region_info
*info
,
193 struct module
*owner
)
195 struct fpga_region
*region
;
200 "Attempt to register without required info structure\n");
201 return ERR_PTR(-EINVAL
);
204 region
= kzalloc(sizeof(*region
), GFP_KERNEL
);
206 return ERR_PTR(-ENOMEM
);
208 id
= ida_alloc(&fpga_region_ida
, GFP_KERNEL
);
214 region
->mgr
= info
->mgr
;
215 region
->compat_id
= info
->compat_id
;
216 region
->priv
= info
->priv
;
217 region
->get_bridges
= info
->get_bridges
;
218 region
->ops_owner
= owner
;
220 mutex_init(®ion
->mutex
);
221 INIT_LIST_HEAD(®ion
->bridge_list
);
223 region
->dev
.class = &fpga_region_class
;
224 region
->dev
.parent
= parent
;
225 region
->dev
.of_node
= parent
->of_node
;
228 ret
= dev_set_name(®ion
->dev
, "region%d", id
);
232 ret
= device_register(®ion
->dev
);
234 put_device(®ion
->dev
);
241 ida_free(&fpga_region_ida
, id
);
247 EXPORT_SYMBOL_GPL(__fpga_region_register_full
);
250 * __fpga_region_register - create and register an FPGA Region device
251 * @parent: device parent
252 * @mgr: manager that programs this region
253 * @get_bridges: optional function to get bridges to a list
254 * @owner: module containing the get_bridges function
256 * This simple version of the register function should be sufficient for most users.
257 * The fpga_region_register_full() function is available for users that need to
258 * pass additional, optional parameters.
260 * Return: struct fpga_region or ERR_PTR()
263 __fpga_region_register(struct device
*parent
, struct fpga_manager
*mgr
,
264 int (*get_bridges
)(struct fpga_region
*), struct module
*owner
)
266 struct fpga_region_info info
= { 0 };
269 info
.get_bridges
= get_bridges
;
271 return __fpga_region_register_full(parent
, &info
, owner
);
273 EXPORT_SYMBOL_GPL(__fpga_region_register
);
276 * fpga_region_unregister - unregister an FPGA region
277 * @region: FPGA region
279 * This function is intended for use in an FPGA region driver's remove function.
281 void fpga_region_unregister(struct fpga_region
*region
)
283 device_unregister(®ion
->dev
);
285 EXPORT_SYMBOL_GPL(fpga_region_unregister
);
287 static void fpga_region_dev_release(struct device
*dev
)
289 struct fpga_region
*region
= to_fpga_region(dev
);
291 ida_free(&fpga_region_ida
, region
->dev
.id
);
295 static const struct class fpga_region_class
= {
296 .name
= "fpga_region",
297 .dev_groups
= fpga_region_groups
,
298 .dev_release
= fpga_region_dev_release
,
302 * fpga_region_init - creates the fpga_region class.
304 * Return: 0 on success or ERR_PTR() on error.
306 static int __init
fpga_region_init(void)
308 return class_register(&fpga_region_class
);
311 static void __exit
fpga_region_exit(void)
313 class_unregister(&fpga_region_class
);
314 ida_destroy(&fpga_region_ida
);
317 subsys_initcall(fpga_region_init
);
318 module_exit(fpga_region_exit
);
320 MODULE_DESCRIPTION("FPGA Region");
321 MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
322 MODULE_LICENSE("GPL v2");