1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * FPGA Bridge Framework Driver |
4 | * |
5 | * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. |
6 | * Copyright (C) 2017 Intel Corporation |
7 | */ |
8 | #include <linux/fpga/fpga-bridge.h> |
9 | #include <linux/idr.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/of_platform.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/spinlock.h> |
15 | |
16 | static DEFINE_IDA(fpga_bridge_ida); |
17 | static const struct class fpga_bridge_class; |
18 | |
19 | /* Lock for adding/removing bridges to linked lists*/ |
20 | static DEFINE_SPINLOCK(bridge_list_lock); |
21 | |
22 | /** |
23 | * fpga_bridge_enable - Enable transactions on the bridge |
24 | * |
25 | * @bridge: FPGA bridge |
26 | * |
27 | * Return: 0 for success, error code otherwise. |
28 | */ |
29 | int fpga_bridge_enable(struct fpga_bridge *bridge) |
30 | { |
31 | dev_dbg(&bridge->dev, "enable\n" ); |
32 | |
33 | if (bridge->br_ops && bridge->br_ops->enable_set) |
34 | return bridge->br_ops->enable_set(bridge, 1); |
35 | |
36 | return 0; |
37 | } |
38 | EXPORT_SYMBOL_GPL(fpga_bridge_enable); |
39 | |
40 | /** |
41 | * fpga_bridge_disable - Disable transactions on the bridge |
42 | * |
43 | * @bridge: FPGA bridge |
44 | * |
45 | * Return: 0 for success, error code otherwise. |
46 | */ |
47 | int fpga_bridge_disable(struct fpga_bridge *bridge) |
48 | { |
49 | dev_dbg(&bridge->dev, "disable\n" ); |
50 | |
51 | if (bridge->br_ops && bridge->br_ops->enable_set) |
52 | return bridge->br_ops->enable_set(bridge, 0); |
53 | |
54 | return 0; |
55 | } |
56 | EXPORT_SYMBOL_GPL(fpga_bridge_disable); |
57 | |
58 | static struct fpga_bridge *__fpga_bridge_get(struct device *dev, |
59 | struct fpga_image_info *info) |
60 | { |
61 | struct fpga_bridge *bridge; |
62 | int ret = -ENODEV; |
63 | |
64 | bridge = to_fpga_bridge(dev); |
65 | |
66 | bridge->info = info; |
67 | |
68 | if (!mutex_trylock(lock: &bridge->mutex)) { |
69 | ret = -EBUSY; |
70 | goto err_dev; |
71 | } |
72 | |
73 | if (!try_module_get(module: dev->parent->driver->owner)) |
74 | goto err_ll_mod; |
75 | |
76 | dev_dbg(&bridge->dev, "get\n" ); |
77 | |
78 | return bridge; |
79 | |
80 | err_ll_mod: |
81 | mutex_unlock(lock: &bridge->mutex); |
82 | err_dev: |
83 | put_device(dev); |
84 | return ERR_PTR(error: ret); |
85 | } |
86 | |
87 | /** |
88 | * of_fpga_bridge_get - get an exclusive reference to an fpga bridge |
89 | * |
90 | * @np: node pointer of an FPGA bridge. |
91 | * @info: fpga image specific information. |
92 | * |
93 | * Return: |
94 | * * fpga_bridge struct pointer if successful. |
95 | * * -EBUSY if someone already has a reference to the bridge. |
96 | * * -ENODEV if @np is not an FPGA Bridge or can't take parent driver refcount. |
97 | */ |
98 | struct fpga_bridge *of_fpga_bridge_get(struct device_node *np, |
99 | struct fpga_image_info *info) |
100 | { |
101 | struct device *dev; |
102 | |
103 | dev = class_find_device_by_of_node(class: &fpga_bridge_class, np); |
104 | if (!dev) |
105 | return ERR_PTR(error: -ENODEV); |
106 | |
107 | return __fpga_bridge_get(dev, info); |
108 | } |
109 | EXPORT_SYMBOL_GPL(of_fpga_bridge_get); |
110 | |
111 | static int fpga_bridge_dev_match(struct device *dev, const void *data) |
112 | { |
113 | return dev->parent == data; |
114 | } |
115 | |
116 | /** |
117 | * fpga_bridge_get - get an exclusive reference to an fpga bridge |
118 | * @dev: parent device that fpga bridge was registered with |
119 | * @info: fpga image specific information |
120 | * |
121 | * Given a device, get an exclusive reference to an fpga bridge. |
122 | * |
123 | * Return: fpga bridge struct or IS_ERR() condition containing error code. |
124 | */ |
125 | struct fpga_bridge *fpga_bridge_get(struct device *dev, |
126 | struct fpga_image_info *info) |
127 | { |
128 | struct device *bridge_dev; |
129 | |
130 | bridge_dev = class_find_device(class: &fpga_bridge_class, NULL, data: dev, |
131 | match: fpga_bridge_dev_match); |
132 | if (!bridge_dev) |
133 | return ERR_PTR(error: -ENODEV); |
134 | |
135 | return __fpga_bridge_get(dev: bridge_dev, info); |
136 | } |
137 | EXPORT_SYMBOL_GPL(fpga_bridge_get); |
138 | |
139 | /** |
140 | * fpga_bridge_put - release a reference to a bridge |
141 | * |
142 | * @bridge: FPGA bridge |
143 | */ |
144 | void fpga_bridge_put(struct fpga_bridge *bridge) |
145 | { |
146 | dev_dbg(&bridge->dev, "put\n" ); |
147 | |
148 | bridge->info = NULL; |
149 | module_put(module: bridge->dev.parent->driver->owner); |
150 | mutex_unlock(lock: &bridge->mutex); |
151 | put_device(dev: &bridge->dev); |
152 | } |
153 | EXPORT_SYMBOL_GPL(fpga_bridge_put); |
154 | |
155 | /** |
156 | * fpga_bridges_enable - enable bridges in a list |
157 | * @bridge_list: list of FPGA bridges |
158 | * |
159 | * Enable each bridge in the list. If list is empty, do nothing. |
160 | * |
161 | * Return: 0 for success or empty bridge list or an error code otherwise. |
162 | */ |
163 | int fpga_bridges_enable(struct list_head *bridge_list) |
164 | { |
165 | struct fpga_bridge *bridge; |
166 | int ret; |
167 | |
168 | list_for_each_entry(bridge, bridge_list, node) { |
169 | ret = fpga_bridge_enable(bridge); |
170 | if (ret) |
171 | return ret; |
172 | } |
173 | |
174 | return 0; |
175 | } |
176 | EXPORT_SYMBOL_GPL(fpga_bridges_enable); |
177 | |
178 | /** |
179 | * fpga_bridges_disable - disable bridges in a list |
180 | * |
181 | * @bridge_list: list of FPGA bridges |
182 | * |
183 | * Disable each bridge in the list. If list is empty, do nothing. |
184 | * |
185 | * Return: 0 for success or empty bridge list or an error code otherwise. |
186 | */ |
187 | int fpga_bridges_disable(struct list_head *bridge_list) |
188 | { |
189 | struct fpga_bridge *bridge; |
190 | int ret; |
191 | |
192 | list_for_each_entry(bridge, bridge_list, node) { |
193 | ret = fpga_bridge_disable(bridge); |
194 | if (ret) |
195 | return ret; |
196 | } |
197 | |
198 | return 0; |
199 | } |
200 | EXPORT_SYMBOL_GPL(fpga_bridges_disable); |
201 | |
202 | /** |
203 | * fpga_bridges_put - put bridges |
204 | * |
205 | * @bridge_list: list of FPGA bridges |
206 | * |
207 | * For each bridge in the list, put the bridge and remove it from the list. |
208 | * If list is empty, do nothing. |
209 | */ |
210 | void fpga_bridges_put(struct list_head *bridge_list) |
211 | { |
212 | struct fpga_bridge *bridge, *next; |
213 | unsigned long flags; |
214 | |
215 | list_for_each_entry_safe(bridge, next, bridge_list, node) { |
216 | fpga_bridge_put(bridge); |
217 | |
218 | spin_lock_irqsave(&bridge_list_lock, flags); |
219 | list_del(entry: &bridge->node); |
220 | spin_unlock_irqrestore(lock: &bridge_list_lock, flags); |
221 | } |
222 | } |
223 | EXPORT_SYMBOL_GPL(fpga_bridges_put); |
224 | |
225 | /** |
226 | * of_fpga_bridge_get_to_list - get a bridge, add it to a list |
227 | * |
228 | * @np: node pointer of an FPGA bridge |
229 | * @info: fpga image specific information |
230 | * @bridge_list: list of FPGA bridges |
231 | * |
232 | * Get an exclusive reference to the bridge and it to the list. |
233 | * |
234 | * Return: 0 for success, error code from of_fpga_bridge_get() otherwise. |
235 | */ |
236 | int of_fpga_bridge_get_to_list(struct device_node *np, |
237 | struct fpga_image_info *info, |
238 | struct list_head *bridge_list) |
239 | { |
240 | struct fpga_bridge *bridge; |
241 | unsigned long flags; |
242 | |
243 | bridge = of_fpga_bridge_get(np, info); |
244 | if (IS_ERR(ptr: bridge)) |
245 | return PTR_ERR(ptr: bridge); |
246 | |
247 | spin_lock_irqsave(&bridge_list_lock, flags); |
248 | list_add(new: &bridge->node, head: bridge_list); |
249 | spin_unlock_irqrestore(lock: &bridge_list_lock, flags); |
250 | |
251 | return 0; |
252 | } |
253 | EXPORT_SYMBOL_GPL(of_fpga_bridge_get_to_list); |
254 | |
255 | /** |
256 | * fpga_bridge_get_to_list - given device, get a bridge, add it to a list |
257 | * |
258 | * @dev: FPGA bridge device |
259 | * @info: fpga image specific information |
260 | * @bridge_list: list of FPGA bridges |
261 | * |
262 | * Get an exclusive reference to the bridge and it to the list. |
263 | * |
264 | * Return: 0 for success, error code from fpga_bridge_get() otherwise. |
265 | */ |
266 | int fpga_bridge_get_to_list(struct device *dev, |
267 | struct fpga_image_info *info, |
268 | struct list_head *bridge_list) |
269 | { |
270 | struct fpga_bridge *bridge; |
271 | unsigned long flags; |
272 | |
273 | bridge = fpga_bridge_get(dev, info); |
274 | if (IS_ERR(ptr: bridge)) |
275 | return PTR_ERR(ptr: bridge); |
276 | |
277 | spin_lock_irqsave(&bridge_list_lock, flags); |
278 | list_add(new: &bridge->node, head: bridge_list); |
279 | spin_unlock_irqrestore(lock: &bridge_list_lock, flags); |
280 | |
281 | return 0; |
282 | } |
283 | EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list); |
284 | |
285 | static ssize_t name_show(struct device *dev, |
286 | struct device_attribute *attr, char *buf) |
287 | { |
288 | struct fpga_bridge *bridge = to_fpga_bridge(dev); |
289 | |
290 | return sprintf(buf, fmt: "%s\n" , bridge->name); |
291 | } |
292 | |
293 | static ssize_t state_show(struct device *dev, |
294 | struct device_attribute *attr, char *buf) |
295 | { |
296 | struct fpga_bridge *bridge = to_fpga_bridge(dev); |
297 | int state = 1; |
298 | |
299 | if (bridge->br_ops && bridge->br_ops->enable_show) { |
300 | state = bridge->br_ops->enable_show(bridge); |
301 | if (state < 0) |
302 | return state; |
303 | } |
304 | |
305 | return sysfs_emit(buf, fmt: "%s\n" , state ? "enabled" : "disabled" ); |
306 | } |
307 | |
308 | static DEVICE_ATTR_RO(name); |
309 | static DEVICE_ATTR_RO(state); |
310 | |
311 | static struct attribute *fpga_bridge_attrs[] = { |
312 | &dev_attr_name.attr, |
313 | &dev_attr_state.attr, |
314 | NULL, |
315 | }; |
316 | ATTRIBUTE_GROUPS(fpga_bridge); |
317 | |
318 | /** |
319 | * fpga_bridge_register - create and register an FPGA Bridge device |
320 | * @parent: FPGA bridge device from pdev |
321 | * @name: FPGA bridge name |
322 | * @br_ops: pointer to structure of fpga bridge ops |
323 | * @priv: FPGA bridge private data |
324 | * |
325 | * Return: struct fpga_bridge pointer or ERR_PTR() |
326 | */ |
327 | struct fpga_bridge * |
328 | fpga_bridge_register(struct device *parent, const char *name, |
329 | const struct fpga_bridge_ops *br_ops, |
330 | void *priv) |
331 | { |
332 | struct fpga_bridge *bridge; |
333 | int id, ret; |
334 | |
335 | if (!br_ops) { |
336 | dev_err(parent, "Attempt to register without fpga_bridge_ops\n" ); |
337 | return ERR_PTR(error: -EINVAL); |
338 | } |
339 | |
340 | if (!name || !strlen(name)) { |
341 | dev_err(parent, "Attempt to register with no name!\n" ); |
342 | return ERR_PTR(error: -EINVAL); |
343 | } |
344 | |
345 | bridge = kzalloc(size: sizeof(*bridge), GFP_KERNEL); |
346 | if (!bridge) |
347 | return ERR_PTR(error: -ENOMEM); |
348 | |
349 | id = ida_alloc(ida: &fpga_bridge_ida, GFP_KERNEL); |
350 | if (id < 0) { |
351 | ret = id; |
352 | goto error_kfree; |
353 | } |
354 | |
355 | mutex_init(&bridge->mutex); |
356 | INIT_LIST_HEAD(list: &bridge->node); |
357 | |
358 | bridge->name = name; |
359 | bridge->br_ops = br_ops; |
360 | bridge->priv = priv; |
361 | |
362 | bridge->dev.groups = br_ops->groups; |
363 | bridge->dev.class = &fpga_bridge_class; |
364 | bridge->dev.parent = parent; |
365 | bridge->dev.of_node = parent->of_node; |
366 | bridge->dev.id = id; |
367 | |
368 | ret = dev_set_name(dev: &bridge->dev, name: "br%d" , id); |
369 | if (ret) |
370 | goto error_device; |
371 | |
372 | ret = device_register(dev: &bridge->dev); |
373 | if (ret) { |
374 | put_device(dev: &bridge->dev); |
375 | return ERR_PTR(error: ret); |
376 | } |
377 | |
378 | of_platform_populate(root: bridge->dev.of_node, NULL, NULL, parent: &bridge->dev); |
379 | |
380 | return bridge; |
381 | |
382 | error_device: |
383 | ida_free(&fpga_bridge_ida, id); |
384 | error_kfree: |
385 | kfree(objp: bridge); |
386 | |
387 | return ERR_PTR(error: ret); |
388 | } |
389 | EXPORT_SYMBOL_GPL(fpga_bridge_register); |
390 | |
391 | /** |
392 | * fpga_bridge_unregister - unregister an FPGA bridge |
393 | * |
394 | * @bridge: FPGA bridge struct |
395 | * |
396 | * This function is intended for use in an FPGA bridge driver's remove function. |
397 | */ |
398 | void fpga_bridge_unregister(struct fpga_bridge *bridge) |
399 | { |
400 | /* |
401 | * If the low level driver provides a method for putting bridge into |
402 | * a desired state upon unregister, do it. |
403 | */ |
404 | if (bridge->br_ops && bridge->br_ops->fpga_bridge_remove) |
405 | bridge->br_ops->fpga_bridge_remove(bridge); |
406 | |
407 | device_unregister(dev: &bridge->dev); |
408 | } |
409 | EXPORT_SYMBOL_GPL(fpga_bridge_unregister); |
410 | |
411 | static void fpga_bridge_dev_release(struct device *dev) |
412 | { |
413 | struct fpga_bridge *bridge = to_fpga_bridge(dev); |
414 | |
415 | ida_free(&fpga_bridge_ida, id: bridge->dev.id); |
416 | kfree(objp: bridge); |
417 | } |
418 | |
419 | static const struct class fpga_bridge_class = { |
420 | .name = "fpga_bridge" , |
421 | .dev_groups = fpga_bridge_groups, |
422 | .dev_release = fpga_bridge_dev_release, |
423 | }; |
424 | |
425 | static int __init fpga_bridge_dev_init(void) |
426 | { |
427 | return class_register(class: &fpga_bridge_class); |
428 | } |
429 | |
430 | static void __exit fpga_bridge_dev_exit(void) |
431 | { |
432 | class_unregister(class: &fpga_bridge_class); |
433 | ida_destroy(ida: &fpga_bridge_ida); |
434 | } |
435 | |
436 | MODULE_DESCRIPTION("FPGA Bridge Driver" ); |
437 | MODULE_AUTHOR("Alan Tull <atull@kernel.org>" ); |
438 | MODULE_LICENSE("GPL v2" ); |
439 | |
440 | subsys_initcall(fpga_bridge_dev_init); |
441 | module_exit(fpga_bridge_dev_exit); |
442 | |