diff options
Diffstat (limited to 'drivers/fpga/fpga-bridge.c')
-rw-r--r-- | drivers/fpga/fpga-bridge.c | 110 |
1 files changed, 87 insertions, 23 deletions
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 9651aa56244a..0dfe9d78cee2 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * FPGA Bridge Framework Driver | 2 | * FPGA Bridge Framework Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. | 4 | * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. |
5 | * Copyright (C) 2017 Intel Corporation | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 7 | * 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 | * under the terms and conditions of the GNU General Public License, |
@@ -70,29 +71,12 @@ int fpga_bridge_disable(struct fpga_bridge *bridge) | |||
70 | } | 71 | } |
71 | EXPORT_SYMBOL_GPL(fpga_bridge_disable); | 72 | EXPORT_SYMBOL_GPL(fpga_bridge_disable); |
72 | 73 | ||
73 | /** | 74 | static struct fpga_bridge *__fpga_bridge_get(struct device *dev, |
74 | * of_fpga_bridge_get - get an exclusive reference to a fpga bridge | 75 | struct fpga_image_info *info) |
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 | { | 76 | { |
87 | struct device *dev; | ||
88 | struct fpga_bridge *bridge; | 77 | struct fpga_bridge *bridge; |
89 | int ret = -ENODEV; | 78 | int ret = -ENODEV; |
90 | 79 | ||
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); | 80 | bridge = to_fpga_bridge(dev); |
97 | if (!bridge) | 81 | if (!bridge) |
98 | goto err_dev; | 82 | goto err_dev; |
@@ -117,8 +101,58 @@ err_dev: | |||
117 | put_device(dev); | 101 | put_device(dev); |
118 | return ERR_PTR(ret); | 102 | return ERR_PTR(ret); |
119 | } | 103 | } |
104 | |||
105 | /** | ||
106 | * of_fpga_bridge_get - get an exclusive reference to a fpga bridge | ||
107 | * | ||
108 | * @np: node pointer of a FPGA bridge | ||
109 | * @info: fpga image specific information | ||
110 | * | ||
111 | * Return fpga_bridge struct if successful. | ||
112 | * Return -EBUSY if someone already has a reference to the bridge. | ||
113 | * Return -ENODEV if @np is not a FPGA Bridge. | ||
114 | */ | ||
115 | struct fpga_bridge *of_fpga_bridge_get(struct device_node *np, | ||
116 | struct fpga_image_info *info) | ||
117 | { | ||
118 | struct device *dev; | ||
119 | |||
120 | dev = class_find_device(fpga_bridge_class, NULL, np, | ||
121 | fpga_bridge_of_node_match); | ||
122 | if (!dev) | ||
123 | return ERR_PTR(-ENODEV); | ||
124 | |||
125 | return __fpga_bridge_get(dev, info); | ||
126 | } | ||
120 | EXPORT_SYMBOL_GPL(of_fpga_bridge_get); | 127 | EXPORT_SYMBOL_GPL(of_fpga_bridge_get); |
121 | 128 | ||
129 | static int fpga_bridge_dev_match(struct device *dev, const void *data) | ||
130 | { | ||
131 | return dev->parent == data; | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * fpga_bridge_get - get an exclusive reference to a fpga bridge | ||
136 | * @dev: parent device that fpga bridge was registered with | ||
137 | * | ||
138 | * Given a device, get an exclusive reference to a fpga bridge. | ||
139 | * | ||
140 | * Return: fpga manager struct or IS_ERR() condition containing error code. | ||
141 | */ | ||
142 | struct fpga_bridge *fpga_bridge_get(struct device *dev, | ||
143 | struct fpga_image_info *info) | ||
144 | { | ||
145 | struct device *bridge_dev; | ||
146 | |||
147 | bridge_dev = class_find_device(fpga_bridge_class, NULL, dev, | ||
148 | fpga_bridge_dev_match); | ||
149 | if (!bridge_dev) | ||
150 | return ERR_PTR(-ENODEV); | ||
151 | |||
152 | return __fpga_bridge_get(bridge_dev, info); | ||
153 | } | ||
154 | EXPORT_SYMBOL_GPL(fpga_bridge_get); | ||
155 | |||
122 | /** | 156 | /** |
123 | * fpga_bridge_put - release a reference to a bridge | 157 | * fpga_bridge_put - release a reference to a bridge |
124 | * | 158 | * |
@@ -206,7 +240,7 @@ void fpga_bridges_put(struct list_head *bridge_list) | |||
206 | EXPORT_SYMBOL_GPL(fpga_bridges_put); | 240 | EXPORT_SYMBOL_GPL(fpga_bridges_put); |
207 | 241 | ||
208 | /** | 242 | /** |
209 | * fpga_bridges_get_to_list - get a bridge, add it to a list | 243 | * of_fpga_bridge_get_to_list - get a bridge, add it to a list |
210 | * | 244 | * |
211 | * @np: node pointer of a FPGA bridge | 245 | * @np: node pointer of a FPGA bridge |
212 | * @info: fpga image specific information | 246 | * @info: fpga image specific information |
@@ -216,14 +250,44 @@ EXPORT_SYMBOL_GPL(fpga_bridges_put); | |||
216 | * | 250 | * |
217 | * Return 0 for success, error code from of_fpga_bridge_get() othewise. | 251 | * Return 0 for success, error code from of_fpga_bridge_get() othewise. |
218 | */ | 252 | */ |
219 | int fpga_bridge_get_to_list(struct device_node *np, | 253 | int of_fpga_bridge_get_to_list(struct device_node *np, |
254 | struct fpga_image_info *info, | ||
255 | struct list_head *bridge_list) | ||
256 | { | ||
257 | struct fpga_bridge *bridge; | ||
258 | unsigned long flags; | ||
259 | |||
260 | bridge = of_fpga_bridge_get(np, info); | ||
261 | if (IS_ERR(bridge)) | ||
262 | return PTR_ERR(bridge); | ||
263 | |||
264 | spin_lock_irqsave(&bridge_list_lock, flags); | ||
265 | list_add(&bridge->node, bridge_list); | ||
266 | spin_unlock_irqrestore(&bridge_list_lock, flags); | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | EXPORT_SYMBOL_GPL(of_fpga_bridge_get_to_list); | ||
271 | |||
272 | /** | ||
273 | * fpga_bridge_get_to_list - given device, get a bridge, add it to a list | ||
274 | * | ||
275 | * @dev: FPGA bridge device | ||
276 | * @info: fpga image specific information | ||
277 | * @bridge_list: list of FPGA bridges | ||
278 | * | ||
279 | * Get an exclusive reference to the bridge and and it to the list. | ||
280 | * | ||
281 | * Return 0 for success, error code from fpga_bridge_get() othewise. | ||
282 | */ | ||
283 | int fpga_bridge_get_to_list(struct device *dev, | ||
220 | struct fpga_image_info *info, | 284 | struct fpga_image_info *info, |
221 | struct list_head *bridge_list) | 285 | struct list_head *bridge_list) |
222 | { | 286 | { |
223 | struct fpga_bridge *bridge; | 287 | struct fpga_bridge *bridge; |
224 | unsigned long flags; | 288 | unsigned long flags; |
225 | 289 | ||
226 | bridge = of_fpga_bridge_get(np, info); | 290 | bridge = fpga_bridge_get(dev, info); |
227 | if (IS_ERR(bridge)) | 291 | if (IS_ERR(bridge)) |
228 | return PTR_ERR(bridge); | 292 | return PTR_ERR(bridge); |
229 | 293 | ||
@@ -381,7 +445,7 @@ static void __exit fpga_bridge_dev_exit(void) | |||
381 | } | 445 | } |
382 | 446 | ||
383 | MODULE_DESCRIPTION("FPGA Bridge Driver"); | 447 | MODULE_DESCRIPTION("FPGA Bridge Driver"); |
384 | MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>"); | 448 | MODULE_AUTHOR("Alan Tull <atull@kernel.org>"); |
385 | MODULE_LICENSE("GPL v2"); | 449 | MODULE_LICENSE("GPL v2"); |
386 | 450 | ||
387 | subsys_initcall(fpga_bridge_dev_init); | 451 | subsys_initcall(fpga_bridge_dev_init); |