]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/fpga/fpga-bridge.c
UBUNTU: Ubuntu-4.15.0-96.97
[mirror_ubuntu-bionic-kernel.git] / drivers / fpga / fpga-bridge.c
CommitLineData
21aeda95
AT
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
26static DEFINE_IDA(fpga_bridge_ida);
27static struct class *fpga_bridge_class;
28
29/* Lock for adding/removing bridges to linked lists*/
47910a49 30static spinlock_t bridge_list_lock;
21aeda95
AT
31
32static 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 */
44int 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}
53EXPORT_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 */
62int 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}
71EXPORT_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 */
83struct 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
114err_ll_mod:
115 mutex_unlock(&bridge->mutex);
116err_dev:
117 put_device(dev);
118 return ERR_PTR(ret);
119}
120EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
121
122/**
123 * fpga_bridge_put - release a reference to a bridge
124 *
125 * @bridge: FPGA bridge
126 */
127void 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}
136EXPORT_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 */
146int fpga_bridges_enable(struct list_head *bridge_list)
147{
148 struct fpga_bridge *bridge;
21aeda95
AT
149 int ret;
150
c37235cc 151 list_for_each_entry(bridge, bridge_list, node) {
21aeda95
AT
152 ret = fpga_bridge_enable(bridge);
153 if (ret)
154 return ret;
155 }
156
157 return 0;
158}
159EXPORT_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 */
170int fpga_bridges_disable(struct list_head *bridge_list)
171{
172 struct fpga_bridge *bridge;
21aeda95
AT
173 int ret;
174
c37235cc 175 list_for_each_entry(bridge, bridge_list, node) {
21aeda95
AT
176 ret = fpga_bridge_disable(bridge);
177 if (ret)
178 return ret;
179 }
180
181 return 0;
182}
183EXPORT_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 */
193void fpga_bridges_put(struct list_head *bridge_list)
194{
c37235cc 195 struct fpga_bridge *bridge, *next;
21aeda95
AT
196 unsigned long flags;
197
c37235cc 198 list_for_each_entry_safe(bridge, next, bridge_list, node) {
21aeda95
AT
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}
206EXPORT_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 */
219int 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}
236EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
237
238static 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
246static 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
258static DEVICE_ATTR_RO(name);
259static DEVICE_ATTR_RO(state);
260
261static struct attribute *fpga_bridge_attrs[] = {
262 &dev_attr_name.attr,
263 &dev_attr_state.attr,
264 NULL,
265};
266ATTRIBUTE_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 */
277int 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
327error_device:
328 ida_simple_remove(&fpga_bridge_ida, id);
329error_kfree:
330 kfree(bridge);
331
332 return ret;
333}
334EXPORT_SYMBOL_GPL(fpga_bridge_register);
335
336/**
337 * fpga_bridge_unregister - unregister a fpga bridge driver
338 * @dev: FPGA bridge device from pdev
339 */
340void 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}
353EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
354
355static 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
363static 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
377static void __exit fpga_bridge_dev_exit(void)
378{
379 class_destroy(fpga_bridge_class);
380 ida_destroy(&fpga_bridge_ida);
381}
382
383MODULE_DESCRIPTION("FPGA Bridge Driver");
384MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
385MODULE_LICENSE("GPL v2");
386
387subsys_initcall(fpga_bridge_dev_init);
388module_exit(fpga_bridge_dev_exit);