xref: /openbmc/linux/drivers/fpga/fpga-bridge.c (revision dea54fba)
1 /*
2  * FPGA Bridge Framework Driver
3  *
4  *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program.  If not, see <http://www.gnu.org/licenses/>.
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 static DEFINE_IDA(fpga_bridge_ida);
27 static struct class *fpga_bridge_class;
28 
29 /* Lock for adding/removing bridges to linked lists*/
30 static spinlock_t bridge_list_lock;
31 
32 static int fpga_bridge_of_node_match(struct device *dev, const void *data)
33 {
34 	return dev->of_node == data;
35 }
36 
37 /**
38  * fpga_bridge_enable - Enable transactions on the bridge
39  *
40  * @bridge: FPGA bridge
41  *
42  * Return: 0 for success, error code otherwise.
43  */
44 int fpga_bridge_enable(struct fpga_bridge *bridge)
45 {
46 	dev_dbg(&bridge->dev, "enable\n");
47 
48 	if (bridge->br_ops && bridge->br_ops->enable_set)
49 		return bridge->br_ops->enable_set(bridge, 1);
50 
51 	return 0;
52 }
53 EXPORT_SYMBOL_GPL(fpga_bridge_enable);
54 
55 /**
56  * fpga_bridge_disable - Disable transactions on the bridge
57  *
58  * @bridge: FPGA bridge
59  *
60  * Return: 0 for success, error code otherwise.
61  */
62 int fpga_bridge_disable(struct fpga_bridge *bridge)
63 {
64 	dev_dbg(&bridge->dev, "disable\n");
65 
66 	if (bridge->br_ops && bridge->br_ops->enable_set)
67 		return bridge->br_ops->enable_set(bridge, 0);
68 
69 	return 0;
70 }
71 EXPORT_SYMBOL_GPL(fpga_bridge_disable);
72 
73 /**
74  * of_fpga_bridge_get - get an exclusive reference to a fpga bridge
75  *
76  * @np: node pointer of a FPGA bridge
77  * @info: fpga image specific information
78  *
79  * Return fpga_bridge struct if successful.
80  * Return -EBUSY if someone already has a reference to the bridge.
81  * Return -ENODEV if @np is not a FPGA Bridge.
82  */
83 struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
84 				       struct fpga_image_info *info)
85 
86 {
87 	struct device *dev;
88 	struct fpga_bridge *bridge;
89 	int ret = -ENODEV;
90 
91 	dev = class_find_device(fpga_bridge_class, NULL, np,
92 				fpga_bridge_of_node_match);
93 	if (!dev)
94 		goto err_dev;
95 
96 	bridge = to_fpga_bridge(dev);
97 	if (!bridge)
98 		goto err_dev;
99 
100 	bridge->info = info;
101 
102 	if (!mutex_trylock(&bridge->mutex)) {
103 		ret = -EBUSY;
104 		goto err_dev;
105 	}
106 
107 	if (!try_module_get(dev->parent->driver->owner))
108 		goto err_ll_mod;
109 
110 	dev_dbg(&bridge->dev, "get\n");
111 
112 	return bridge;
113 
114 err_ll_mod:
115 	mutex_unlock(&bridge->mutex);
116 err_dev:
117 	put_device(dev);
118 	return ERR_PTR(ret);
119 }
120 EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
121 
122 /**
123  * fpga_bridge_put - release a reference to a bridge
124  *
125  * @bridge: FPGA bridge
126  */
127 void fpga_bridge_put(struct fpga_bridge *bridge)
128 {
129 	dev_dbg(&bridge->dev, "put\n");
130 
131 	bridge->info = NULL;
132 	module_put(bridge->dev.parent->driver->owner);
133 	mutex_unlock(&bridge->mutex);
134 	put_device(&bridge->dev);
135 }
136 EXPORT_SYMBOL_GPL(fpga_bridge_put);
137 
138 /**
139  * fpga_bridges_enable - enable bridges in a list
140  * @bridge_list: list of FPGA bridges
141  *
142  * Enable each bridge in the list.  If list is empty, do nothing.
143  *
144  * Return 0 for success or empty bridge list; return error code otherwise.
145  */
146 int fpga_bridges_enable(struct list_head *bridge_list)
147 {
148 	struct fpga_bridge *bridge;
149 	int ret;
150 
151 	list_for_each_entry(bridge, bridge_list, node) {
152 		ret = fpga_bridge_enable(bridge);
153 		if (ret)
154 			return ret;
155 	}
156 
157 	return 0;
158 }
159 EXPORT_SYMBOL_GPL(fpga_bridges_enable);
160 
161 /**
162  * fpga_bridges_disable - disable bridges in a list
163  *
164  * @bridge_list: list of FPGA bridges
165  *
166  * Disable each bridge in the list.  If list is empty, do nothing.
167  *
168  * Return 0 for success or empty bridge list; return error code otherwise.
169  */
170 int fpga_bridges_disable(struct list_head *bridge_list)
171 {
172 	struct fpga_bridge *bridge;
173 	int ret;
174 
175 	list_for_each_entry(bridge, bridge_list, node) {
176 		ret = fpga_bridge_disable(bridge);
177 		if (ret)
178 			return ret;
179 	}
180 
181 	return 0;
182 }
183 EXPORT_SYMBOL_GPL(fpga_bridges_disable);
184 
185 /**
186  * fpga_bridges_put - put bridges
187  *
188  * @bridge_list: list of FPGA bridges
189  *
190  * For each bridge in the list, put the bridge and remove it from the list.
191  * If list is empty, do nothing.
192  */
193 void fpga_bridges_put(struct list_head *bridge_list)
194 {
195 	struct fpga_bridge *bridge, *next;
196 	unsigned long flags;
197 
198 	list_for_each_entry_safe(bridge, next, bridge_list, node) {
199 		fpga_bridge_put(bridge);
200 
201 		spin_lock_irqsave(&bridge_list_lock, flags);
202 		list_del(&bridge->node);
203 		spin_unlock_irqrestore(&bridge_list_lock, flags);
204 	}
205 }
206 EXPORT_SYMBOL_GPL(fpga_bridges_put);
207 
208 /**
209  * fpga_bridges_get_to_list - get a bridge, add it to a list
210  *
211  * @np: node pointer of a FPGA bridge
212  * @info: fpga image specific information
213  * @bridge_list: list of FPGA bridges
214  *
215  * Get an exclusive reference to the bridge and and it to the list.
216  *
217  * Return 0 for success, error code from of_fpga_bridge_get() othewise.
218  */
219 int fpga_bridge_get_to_list(struct device_node *np,
220 			    struct fpga_image_info *info,
221 			    struct list_head *bridge_list)
222 {
223 	struct fpga_bridge *bridge;
224 	unsigned long flags;
225 
226 	bridge = of_fpga_bridge_get(np, info);
227 	if (IS_ERR(bridge))
228 		return PTR_ERR(bridge);
229 
230 	spin_lock_irqsave(&bridge_list_lock, flags);
231 	list_add(&bridge->node, bridge_list);
232 	spin_unlock_irqrestore(&bridge_list_lock, flags);
233 
234 	return 0;
235 }
236 EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
237 
238 static ssize_t name_show(struct device *dev,
239 			 struct device_attribute *attr, char *buf)
240 {
241 	struct fpga_bridge *bridge = to_fpga_bridge(dev);
242 
243 	return sprintf(buf, "%s\n", bridge->name);
244 }
245 
246 static ssize_t state_show(struct device *dev,
247 			  struct device_attribute *attr, char *buf)
248 {
249 	struct fpga_bridge *bridge = to_fpga_bridge(dev);
250 	int enable = 1;
251 
252 	if (bridge->br_ops && bridge->br_ops->enable_show)
253 		enable = bridge->br_ops->enable_show(bridge);
254 
255 	return sprintf(buf, "%s\n", enable ? "enabled" : "disabled");
256 }
257 
258 static DEVICE_ATTR_RO(name);
259 static DEVICE_ATTR_RO(state);
260 
261 static struct attribute *fpga_bridge_attrs[] = {
262 	&dev_attr_name.attr,
263 	&dev_attr_state.attr,
264 	NULL,
265 };
266 ATTRIBUTE_GROUPS(fpga_bridge);
267 
268 /**
269  * fpga_bridge_register - register a fpga bridge driver
270  * @dev:	FPGA bridge device from pdev
271  * @name:	FPGA bridge name
272  * @br_ops:	pointer to structure of fpga bridge ops
273  * @priv:	FPGA bridge private data
274  *
275  * Return: 0 for success, error code otherwise.
276  */
277 int fpga_bridge_register(struct device *dev, const char *name,
278 			 const struct fpga_bridge_ops *br_ops, void *priv)
279 {
280 	struct fpga_bridge *bridge;
281 	int id, ret = 0;
282 
283 	if (!name || !strlen(name)) {
284 		dev_err(dev, "Attempt to register with no name!\n");
285 		return -EINVAL;
286 	}
287 
288 	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
289 	if (!bridge)
290 		return -ENOMEM;
291 
292 	id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
293 	if (id < 0) {
294 		ret = id;
295 		goto error_kfree;
296 	}
297 
298 	mutex_init(&bridge->mutex);
299 	INIT_LIST_HEAD(&bridge->node);
300 
301 	bridge->name = name;
302 	bridge->br_ops = br_ops;
303 	bridge->priv = priv;
304 
305 	device_initialize(&bridge->dev);
306 	bridge->dev.class = fpga_bridge_class;
307 	bridge->dev.parent = dev;
308 	bridge->dev.of_node = dev->of_node;
309 	bridge->dev.id = id;
310 	dev_set_drvdata(dev, bridge);
311 
312 	ret = dev_set_name(&bridge->dev, "br%d", id);
313 	if (ret)
314 		goto error_device;
315 
316 	ret = device_add(&bridge->dev);
317 	if (ret)
318 		goto error_device;
319 
320 	of_platform_populate(dev->of_node, NULL, NULL, dev);
321 
322 	dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n",
323 		 bridge->name);
324 
325 	return 0;
326 
327 error_device:
328 	ida_simple_remove(&fpga_bridge_ida, id);
329 error_kfree:
330 	kfree(bridge);
331 
332 	return ret;
333 }
334 EXPORT_SYMBOL_GPL(fpga_bridge_register);
335 
336 /**
337  * fpga_bridge_unregister - unregister a fpga bridge driver
338  * @dev: FPGA bridge device from pdev
339  */
340 void fpga_bridge_unregister(struct device *dev)
341 {
342 	struct fpga_bridge *bridge = dev_get_drvdata(dev);
343 
344 	/*
345 	 * If the low level driver provides a method for putting bridge into
346 	 * a desired state upon unregister, do it.
347 	 */
348 	if (bridge->br_ops && bridge->br_ops->fpga_bridge_remove)
349 		bridge->br_ops->fpga_bridge_remove(bridge);
350 
351 	device_unregister(&bridge->dev);
352 }
353 EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
354 
355 static void fpga_bridge_dev_release(struct device *dev)
356 {
357 	struct fpga_bridge *bridge = to_fpga_bridge(dev);
358 
359 	ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
360 	kfree(bridge);
361 }
362 
363 static int __init fpga_bridge_dev_init(void)
364 {
365 	spin_lock_init(&bridge_list_lock);
366 
367 	fpga_bridge_class = class_create(THIS_MODULE, "fpga_bridge");
368 	if (IS_ERR(fpga_bridge_class))
369 		return PTR_ERR(fpga_bridge_class);
370 
371 	fpga_bridge_class->dev_groups = fpga_bridge_groups;
372 	fpga_bridge_class->dev_release = fpga_bridge_dev_release;
373 
374 	return 0;
375 }
376 
377 static void __exit fpga_bridge_dev_exit(void)
378 {
379 	class_destroy(fpga_bridge_class);
380 	ida_destroy(&fpga_bridge_ida);
381 }
382 
383 MODULE_DESCRIPTION("FPGA Bridge Driver");
384 MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
385 MODULE_LICENSE("GPL v2");
386 
387 subsys_initcall(fpga_bridge_dev_init);
388 module_exit(fpga_bridge_dev_exit);
389