1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/fpga/fpga-bridge.h>
19#include <linux/idr.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/of_platform.h>
23#include <linux/slab.h>
24#include <linux/spinlock.h>
25
26
27#ifdef CONFIG_DEBUG_KERNEL
28#undef DEBUG
29#define DEBUG
30#endif
31
32static DEFINE_IDA(fpga_bridge_ida);
33static struct class *fpga_bridge_class;
34
35
36static spinlock_t bridge_list_lock;
37
38static int fpga_bridge_of_node_match(struct device *dev, const void *data)
39{
40 return dev->of_node == data;
41}
42
43
44
45
46
47
48
49
50int fpga_bridge_enable(struct fpga_bridge *bridge)
51{
52 dev_dbg(&bridge->dev, "enable\n");
53
54 if (bridge->br_ops && bridge->br_ops->enable_set)
55 return bridge->br_ops->enable_set(bridge, 1);
56
57 return 0;
58}
59EXPORT_SYMBOL_GPL(fpga_bridge_enable);
60
61
62
63
64
65
66
67
68int fpga_bridge_disable(struct fpga_bridge *bridge)
69{
70 dev_dbg(&bridge->dev, "disable\n");
71
72 if (bridge->br_ops && bridge->br_ops->enable_set)
73 return bridge->br_ops->enable_set(bridge, 0);
74
75 return 0;
76}
77EXPORT_SYMBOL_GPL(fpga_bridge_disable);
78
79
80
81
82
83
84
85
86
87
88
89struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
90 struct fpga_image_info *info)
91
92{
93 struct device *dev;
94 struct fpga_bridge *bridge;
95 int ret = -ENODEV;
96
97 dev = class_find_device(fpga_bridge_class, NULL, np,
98 fpga_bridge_of_node_match);
99 if (!dev)
100 goto err_dev;
101
102 bridge = to_fpga_bridge(dev);
103 if (!bridge)
104 goto err_dev;
105
106 bridge->info = info;
107
108 if (!mutex_trylock(&bridge->mutex)) {
109 ret = -EBUSY;
110 goto err_dev;
111 }
112
113 if (!try_module_get(dev->parent->driver->owner))
114 goto err_ll_mod;
115
116 dev_dbg(&bridge->dev, "get\n");
117
118 return bridge;
119
120err_ll_mod:
121 mutex_unlock(&bridge->mutex);
122err_dev:
123 put_device(dev);
124 return ERR_PTR(ret);
125}
126EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
127
128
129
130
131
132
133void fpga_bridge_put(struct fpga_bridge *bridge)
134{
135 dev_dbg(&bridge->dev, "put\n");
136
137 bridge->info = NULL;
138 module_put(bridge->dev.parent->driver->owner);
139 mutex_unlock(&bridge->mutex);
140 put_device(&bridge->dev);
141}
142EXPORT_SYMBOL_GPL(fpga_bridge_put);
143
144
145
146
147
148
149
150
151
152int fpga_bridges_enable(struct list_head *bridge_list)
153{
154 struct fpga_bridge *bridge;
155 struct list_head *node;
156 int ret;
157
158 list_for_each(node, bridge_list) {
159 bridge = list_entry(node, struct fpga_bridge, node);
160 ret = fpga_bridge_enable(bridge);
161 if (ret)
162 return ret;
163 }
164
165 return 0;
166}
167EXPORT_SYMBOL_GPL(fpga_bridges_enable);
168
169
170
171
172
173
174
175
176
177
178int fpga_bridges_disable(struct list_head *bridge_list)
179{
180 struct fpga_bridge *bridge;
181 struct list_head *node;
182 int ret;
183
184 list_for_each(node, bridge_list) {
185 bridge = list_entry(node, struct fpga_bridge, node);
186 ret = fpga_bridge_disable(bridge);
187 if (ret)
188 return ret;
189 }
190
191 return 0;
192}
193EXPORT_SYMBOL_GPL(fpga_bridges_disable);
194
195
196
197
198
199
200
201
202
203void fpga_bridges_put(struct list_head *bridge_list)
204{
205 struct fpga_bridge *bridge;
206 struct list_head *node, *next;
207 unsigned long flags;
208
209 list_for_each_safe(node, next, bridge_list) {
210 bridge = list_entry(node, struct fpga_bridge, node);
211
212 fpga_bridge_put(bridge);
213
214 spin_lock_irqsave(&bridge_list_lock, flags);
215 list_del(&bridge->node);
216 spin_unlock_irqrestore(&bridge_list_lock, flags);
217 }
218}
219EXPORT_SYMBOL_GPL(fpga_bridges_put);
220
221
222
223
224
225
226
227
228
229
230
231
232int fpga_bridge_get_to_list(struct device_node *np,
233 struct fpga_image_info *info,
234 struct list_head *bridge_list)
235{
236 struct fpga_bridge *bridge;
237 unsigned long flags;
238
239 bridge = of_fpga_bridge_get(np, info);
240 if (IS_ERR(bridge))
241 return PTR_ERR(bridge);
242
243 spin_lock_irqsave(&bridge_list_lock, flags);
244 list_add(&bridge->node, bridge_list);
245 spin_unlock_irqrestore(&bridge_list_lock, flags);
246
247 return 0;
248}
249EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
250
251static ssize_t name_show(struct device *dev,
252 struct device_attribute *attr, char *buf)
253{
254 struct fpga_bridge *bridge = to_fpga_bridge(dev);
255
256 return sprintf(buf, "%s\n", bridge->name);
257}
258
259static ssize_t state_show(struct device *dev,
260 struct device_attribute *attr, char *buf)
261{
262 struct fpga_bridge *bridge = to_fpga_bridge(dev);
263 int enable = 1;
264
265 if (bridge->br_ops && bridge->br_ops->enable_show)
266 enable = bridge->br_ops->enable_show(bridge);
267
268 return sprintf(buf, "%s\n", enable ? "enabled" : "disabled");
269}
270
271static DEVICE_ATTR_RO(name);
272static DEVICE_ATTR_RO(state);
273
274#ifdef DEBUG
275static ssize_t set_store(struct device *dev,
276 struct device_attribute *attr,
277 const char *buf, size_t count)
278{
279 struct fpga_bridge *bridge = to_fpga_bridge(dev);
280 long enable;
281 int ret;
282
283 ret = kstrtol(buf, 16, &enable);
284 if (ret)
285 return ret;
286
287 if (bridge->br_ops && bridge->br_ops->enable_set)
288 enable = bridge->br_ops->enable_set(bridge, !!enable);
289
290 return count;
291}
292static DEVICE_ATTR_WO(set);
293#endif
294
295static struct attribute *fpga_bridge_attrs[] = {
296 &dev_attr_name.attr,
297 &dev_attr_state.attr,
298#ifdef DEBUG
299 &dev_attr_set.attr,
300#endif
301 NULL,
302};
303ATTRIBUTE_GROUPS(fpga_bridge);
304
305
306
307
308
309
310
311
312
313
314int fpga_bridge_register(struct device *dev, const char *name,
315 const struct fpga_bridge_ops *br_ops, void *priv)
316{
317 struct fpga_bridge *bridge;
318 int id, ret = 0;
319
320 if (!name || !strlen(name)) {
321 dev_err(dev, "Attempt to register with no name!\n");
322 return -EINVAL;
323 }
324
325 bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
326 if (!bridge)
327 return -ENOMEM;
328
329 id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
330 if (id < 0) {
331 ret = id;
332 goto error_kfree;
333 }
334
335 mutex_init(&bridge->mutex);
336 INIT_LIST_HEAD(&bridge->node);
337
338 bridge->name = name;
339 bridge->br_ops = br_ops;
340 bridge->priv = priv;
341
342 device_initialize(&bridge->dev);
343 bridge->dev.class = fpga_bridge_class;
344 bridge->dev.parent = dev;
345 bridge->dev.of_node = dev->of_node;
346 bridge->dev.id = id;
347 dev_set_drvdata(dev, bridge);
348
349 ret = dev_set_name(&bridge->dev, "br%d", id);
350 if (ret)
351 goto error_device;
352
353 ret = device_add(&bridge->dev);
354 if (ret)
355 goto error_device;
356
357 of_platform_populate(dev->of_node, NULL, NULL, dev);
358
359 dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n",
360 bridge->name);
361
362 return 0;
363
364error_device:
365 ida_simple_remove(&fpga_bridge_ida, id);
366error_kfree:
367 kfree(bridge);
368
369 return ret;
370}
371EXPORT_SYMBOL_GPL(fpga_bridge_register);
372
373
374
375
376
377void fpga_bridge_unregister(struct device *dev)
378{
379 struct fpga_bridge *bridge = dev_get_drvdata(dev);
380
381
382
383
384
385 if (bridge->br_ops && bridge->br_ops->fpga_bridge_remove)
386 bridge->br_ops->fpga_bridge_remove(bridge);
387
388 device_unregister(&bridge->dev);
389}
390EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
391
392static void fpga_bridge_dev_release(struct device *dev)
393{
394 struct fpga_bridge *bridge = to_fpga_bridge(dev);
395
396 ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
397 kfree(bridge);
398}
399
400static int __init fpga_bridge_dev_init(void)
401{
402 spin_lock_init(&bridge_list_lock);
403
404 fpga_bridge_class = class_create(THIS_MODULE, "fpga_bridge");
405 if (IS_ERR(fpga_bridge_class))
406 return PTR_ERR(fpga_bridge_class);
407
408 fpga_bridge_class->dev_groups = fpga_bridge_groups;
409 fpga_bridge_class->dev_release = fpga_bridge_dev_release;
410
411 return 0;
412}
413
414static void __exit fpga_bridge_dev_exit(void)
415{
416 class_destroy(fpga_bridge_class);
417 ida_destroy(&fpga_bridge_ida);
418}
419
420MODULE_DESCRIPTION("FPGA Bridge Driver");
421MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
422MODULE_LICENSE("GPL v2");
423
424subsys_initcall(fpga_bridge_dev_init);
425module_exit(fpga_bridge_dev_exit);
426