1473f01f7SAlan Tull // SPDX-License-Identifier: GPL-2.0
221aeda95SAlan Tull /*
321aeda95SAlan Tull * FPGA Bridge Framework Driver
421aeda95SAlan Tull *
521aeda95SAlan Tull * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
69c1c4b27SAlan Tull * Copyright (C) 2017 Intel Corporation
721aeda95SAlan Tull */
821aeda95SAlan Tull #include <linux/fpga/fpga-bridge.h>
921aeda95SAlan Tull #include <linux/idr.h>
1021aeda95SAlan Tull #include <linux/kernel.h>
1121aeda95SAlan Tull #include <linux/module.h>
1221aeda95SAlan Tull #include <linux/of_platform.h>
1321aeda95SAlan Tull #include <linux/slab.h>
1421aeda95SAlan Tull #include <linux/spinlock.h>
1521aeda95SAlan Tull
1621aeda95SAlan Tull static DEFINE_IDA(fpga_bridge_ida);
177bb2d219SIvan Orlov static const struct class fpga_bridge_class;
1821aeda95SAlan Tull
1921aeda95SAlan Tull /* Lock for adding/removing bridges to linked lists*/
20f5187329SZheng Yongjun static DEFINE_SPINLOCK(bridge_list_lock);
2121aeda95SAlan Tull
2221aeda95SAlan Tull /**
2321aeda95SAlan Tull * fpga_bridge_enable - Enable transactions on the bridge
2421aeda95SAlan Tull *
2521aeda95SAlan Tull * @bridge: FPGA bridge
2621aeda95SAlan Tull *
2721aeda95SAlan Tull * Return: 0 for success, error code otherwise.
2821aeda95SAlan Tull */
fpga_bridge_enable(struct fpga_bridge * bridge)2921aeda95SAlan Tull int fpga_bridge_enable(struct fpga_bridge *bridge)
3021aeda95SAlan Tull {
3121aeda95SAlan Tull dev_dbg(&bridge->dev, "enable\n");
3221aeda95SAlan Tull
3321aeda95SAlan Tull if (bridge->br_ops && bridge->br_ops->enable_set)
3421aeda95SAlan Tull return bridge->br_ops->enable_set(bridge, 1);
3521aeda95SAlan Tull
3621aeda95SAlan Tull return 0;
3721aeda95SAlan Tull }
3821aeda95SAlan Tull EXPORT_SYMBOL_GPL(fpga_bridge_enable);
3921aeda95SAlan Tull
4021aeda95SAlan Tull /**
4121aeda95SAlan Tull * fpga_bridge_disable - Disable transactions on the bridge
4221aeda95SAlan Tull *
4321aeda95SAlan Tull * @bridge: FPGA bridge
4421aeda95SAlan Tull *
4521aeda95SAlan Tull * Return: 0 for success, error code otherwise.
4621aeda95SAlan Tull */
fpga_bridge_disable(struct fpga_bridge * bridge)4721aeda95SAlan Tull int fpga_bridge_disable(struct fpga_bridge *bridge)
4821aeda95SAlan Tull {
4921aeda95SAlan Tull dev_dbg(&bridge->dev, "disable\n");
5021aeda95SAlan Tull
5121aeda95SAlan Tull if (bridge->br_ops && bridge->br_ops->enable_set)
5221aeda95SAlan Tull return bridge->br_ops->enable_set(bridge, 0);
5321aeda95SAlan Tull
5421aeda95SAlan Tull return 0;
5521aeda95SAlan Tull }
5621aeda95SAlan Tull EXPORT_SYMBOL_GPL(fpga_bridge_disable);
5721aeda95SAlan Tull
__fpga_bridge_get(struct device * bridge_dev,struct fpga_image_info * info)58*d7c4081cSMarco Pagani static struct fpga_bridge *__fpga_bridge_get(struct device *bridge_dev,
5921aeda95SAlan Tull struct fpga_image_info *info)
6021aeda95SAlan Tull {
6121aeda95SAlan Tull struct fpga_bridge *bridge;
6221aeda95SAlan Tull
63*d7c4081cSMarco Pagani bridge = to_fpga_bridge(bridge_dev);
6421aeda95SAlan Tull
6521aeda95SAlan Tull bridge->info = info;
6621aeda95SAlan Tull
67*d7c4081cSMarco Pagani if (!mutex_trylock(&bridge->mutex))
68*d7c4081cSMarco Pagani return ERR_PTR(-EBUSY);
6921aeda95SAlan Tull
70*d7c4081cSMarco Pagani if (!try_module_get(bridge->br_ops_owner)) {
71*d7c4081cSMarco Pagani mutex_unlock(&bridge->mutex);
72*d7c4081cSMarco Pagani return ERR_PTR(-ENODEV);
73*d7c4081cSMarco Pagani }
7421aeda95SAlan Tull
7521aeda95SAlan Tull dev_dbg(&bridge->dev, "get\n");
7621aeda95SAlan Tull
7721aeda95SAlan Tull return bridge;
7821aeda95SAlan Tull }
799c1c4b27SAlan Tull
809c1c4b27SAlan Tull /**
81e7555cf6STom Rix * of_fpga_bridge_get - get an exclusive reference to an fpga bridge
829c1c4b27SAlan Tull *
838e665c9cSMarco Pagani * @np: node pointer of an FPGA bridge.
848e665c9cSMarco Pagani * @info: fpga image specific information.
859c1c4b27SAlan Tull *
868e665c9cSMarco Pagani * Return:
878e665c9cSMarco Pagani * * fpga_bridge struct pointer if successful.
888e665c9cSMarco Pagani * * -EBUSY if someone already has a reference to the bridge.
898e665c9cSMarco Pagani * * -ENODEV if @np is not an FPGA Bridge or can't take parent driver refcount.
909c1c4b27SAlan Tull */
of_fpga_bridge_get(struct device_node * np,struct fpga_image_info * info)919c1c4b27SAlan Tull struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
929c1c4b27SAlan Tull struct fpga_image_info *info)
939c1c4b27SAlan Tull {
94*d7c4081cSMarco Pagani struct fpga_bridge *bridge;
95*d7c4081cSMarco Pagani struct device *bridge_dev;
969c1c4b27SAlan Tull
97*d7c4081cSMarco Pagani bridge_dev = class_find_device_by_of_node(&fpga_bridge_class, np);
98*d7c4081cSMarco Pagani if (!bridge_dev)
999c1c4b27SAlan Tull return ERR_PTR(-ENODEV);
1009c1c4b27SAlan Tull
101*d7c4081cSMarco Pagani bridge = __fpga_bridge_get(bridge_dev, info);
102*d7c4081cSMarco Pagani if (IS_ERR(bridge))
103*d7c4081cSMarco Pagani put_device(bridge_dev);
104*d7c4081cSMarco Pagani
105*d7c4081cSMarco Pagani return bridge;
1069c1c4b27SAlan Tull }
10721aeda95SAlan Tull EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
10821aeda95SAlan Tull
fpga_bridge_dev_match(struct device * dev,const void * data)1099c1c4b27SAlan Tull static int fpga_bridge_dev_match(struct device *dev, const void *data)
1109c1c4b27SAlan Tull {
1119c1c4b27SAlan Tull return dev->parent == data;
1129c1c4b27SAlan Tull }
1139c1c4b27SAlan Tull
1149c1c4b27SAlan Tull /**
115e7555cf6STom Rix * fpga_bridge_get - get an exclusive reference to an fpga bridge
1169c1c4b27SAlan Tull * @dev: parent device that fpga bridge was registered with
1177ef1a2c1SMarco Pagani * @info: fpga image specific information
1189c1c4b27SAlan Tull *
119e7555cf6STom Rix * Given a device, get an exclusive reference to an fpga bridge.
1209c1c4b27SAlan Tull *
121b4d9a0e5SAlan Tull * Return: fpga bridge struct or IS_ERR() condition containing error code.
1229c1c4b27SAlan Tull */
fpga_bridge_get(struct device * dev,struct fpga_image_info * info)1239c1c4b27SAlan Tull struct fpga_bridge *fpga_bridge_get(struct device *dev,
1249c1c4b27SAlan Tull struct fpga_image_info *info)
1259c1c4b27SAlan Tull {
126*d7c4081cSMarco Pagani struct fpga_bridge *bridge;
1279c1c4b27SAlan Tull struct device *bridge_dev;
1289c1c4b27SAlan Tull
1297bb2d219SIvan Orlov bridge_dev = class_find_device(&fpga_bridge_class, NULL, dev,
1309c1c4b27SAlan Tull fpga_bridge_dev_match);
1319c1c4b27SAlan Tull if (!bridge_dev)
1329c1c4b27SAlan Tull return ERR_PTR(-ENODEV);
1339c1c4b27SAlan Tull
134*d7c4081cSMarco Pagani bridge = __fpga_bridge_get(bridge_dev, info);
135*d7c4081cSMarco Pagani if (IS_ERR(bridge))
136*d7c4081cSMarco Pagani put_device(bridge_dev);
137*d7c4081cSMarco Pagani
138*d7c4081cSMarco Pagani return bridge;
1399c1c4b27SAlan Tull }
1409c1c4b27SAlan Tull EXPORT_SYMBOL_GPL(fpga_bridge_get);
1419c1c4b27SAlan Tull
14221aeda95SAlan Tull /**
14321aeda95SAlan Tull * fpga_bridge_put - release a reference to a bridge
14421aeda95SAlan Tull *
14521aeda95SAlan Tull * @bridge: FPGA bridge
14621aeda95SAlan Tull */
fpga_bridge_put(struct fpga_bridge * bridge)14721aeda95SAlan Tull void fpga_bridge_put(struct fpga_bridge *bridge)
14821aeda95SAlan Tull {
14921aeda95SAlan Tull dev_dbg(&bridge->dev, "put\n");
15021aeda95SAlan Tull
15121aeda95SAlan Tull bridge->info = NULL;
152*d7c4081cSMarco Pagani module_put(bridge->br_ops_owner);
15321aeda95SAlan Tull mutex_unlock(&bridge->mutex);
15421aeda95SAlan Tull put_device(&bridge->dev);
15521aeda95SAlan Tull }
15621aeda95SAlan Tull EXPORT_SYMBOL_GPL(fpga_bridge_put);
15721aeda95SAlan Tull
15821aeda95SAlan Tull /**
15921aeda95SAlan Tull * fpga_bridges_enable - enable bridges in a list
16021aeda95SAlan Tull * @bridge_list: list of FPGA bridges
16121aeda95SAlan Tull *
16221aeda95SAlan Tull * Enable each bridge in the list. If list is empty, do nothing.
16321aeda95SAlan Tull *
1648e665c9cSMarco Pagani * Return: 0 for success or empty bridge list or an error code otherwise.
16521aeda95SAlan Tull */
fpga_bridges_enable(struct list_head * bridge_list)16621aeda95SAlan Tull int fpga_bridges_enable(struct list_head *bridge_list)
16721aeda95SAlan Tull {
16821aeda95SAlan Tull struct fpga_bridge *bridge;
16921aeda95SAlan Tull int ret;
17021aeda95SAlan Tull
171c37235ccSMoritz Fischer list_for_each_entry(bridge, bridge_list, node) {
17221aeda95SAlan Tull ret = fpga_bridge_enable(bridge);
17321aeda95SAlan Tull if (ret)
17421aeda95SAlan Tull return ret;
17521aeda95SAlan Tull }
17621aeda95SAlan Tull
17721aeda95SAlan Tull return 0;
17821aeda95SAlan Tull }
17921aeda95SAlan Tull EXPORT_SYMBOL_GPL(fpga_bridges_enable);
18021aeda95SAlan Tull
18121aeda95SAlan Tull /**
18221aeda95SAlan Tull * fpga_bridges_disable - disable bridges in a list
18321aeda95SAlan Tull *
18421aeda95SAlan Tull * @bridge_list: list of FPGA bridges
18521aeda95SAlan Tull *
18621aeda95SAlan Tull * Disable each bridge in the list. If list is empty, do nothing.
18721aeda95SAlan Tull *
1888e665c9cSMarco Pagani * Return: 0 for success or empty bridge list or an error code otherwise.
18921aeda95SAlan Tull */
fpga_bridges_disable(struct list_head * bridge_list)19021aeda95SAlan Tull int fpga_bridges_disable(struct list_head *bridge_list)
19121aeda95SAlan Tull {
19221aeda95SAlan Tull struct fpga_bridge *bridge;
19321aeda95SAlan Tull int ret;
19421aeda95SAlan Tull
195c37235ccSMoritz Fischer list_for_each_entry(bridge, bridge_list, node) {
19621aeda95SAlan Tull ret = fpga_bridge_disable(bridge);
19721aeda95SAlan Tull if (ret)
19821aeda95SAlan Tull return ret;
19921aeda95SAlan Tull }
20021aeda95SAlan Tull
20121aeda95SAlan Tull return 0;
20221aeda95SAlan Tull }
20321aeda95SAlan Tull EXPORT_SYMBOL_GPL(fpga_bridges_disable);
20421aeda95SAlan Tull
20521aeda95SAlan Tull /**
20621aeda95SAlan Tull * fpga_bridges_put - put bridges
20721aeda95SAlan Tull *
20821aeda95SAlan Tull * @bridge_list: list of FPGA bridges
20921aeda95SAlan Tull *
21021aeda95SAlan Tull * For each bridge in the list, put the bridge and remove it from the list.
21121aeda95SAlan Tull * If list is empty, do nothing.
21221aeda95SAlan Tull */
fpga_bridges_put(struct list_head * bridge_list)21321aeda95SAlan Tull void fpga_bridges_put(struct list_head *bridge_list)
21421aeda95SAlan Tull {
215c37235ccSMoritz Fischer struct fpga_bridge *bridge, *next;
21621aeda95SAlan Tull unsigned long flags;
21721aeda95SAlan Tull
218c37235ccSMoritz Fischer list_for_each_entry_safe(bridge, next, bridge_list, node) {
21921aeda95SAlan Tull fpga_bridge_put(bridge);
22021aeda95SAlan Tull
22121aeda95SAlan Tull spin_lock_irqsave(&bridge_list_lock, flags);
22221aeda95SAlan Tull list_del(&bridge->node);
22321aeda95SAlan Tull spin_unlock_irqrestore(&bridge_list_lock, flags);
22421aeda95SAlan Tull }
22521aeda95SAlan Tull }
22621aeda95SAlan Tull EXPORT_SYMBOL_GPL(fpga_bridges_put);
22721aeda95SAlan Tull
22821aeda95SAlan Tull /**
2299c1c4b27SAlan Tull * of_fpga_bridge_get_to_list - get a bridge, add it to a list
23021aeda95SAlan Tull *
231e7555cf6STom Rix * @np: node pointer of an FPGA bridge
23221aeda95SAlan Tull * @info: fpga image specific information
23321aeda95SAlan Tull * @bridge_list: list of FPGA bridges
23421aeda95SAlan Tull *
2350a05cdf1SNavin Sankar Velliangiri * Get an exclusive reference to the bridge and it to the list.
23621aeda95SAlan Tull *
2378e665c9cSMarco Pagani * Return: 0 for success, error code from of_fpga_bridge_get() otherwise.
23821aeda95SAlan Tull */
of_fpga_bridge_get_to_list(struct device_node * np,struct fpga_image_info * info,struct list_head * bridge_list)2399c1c4b27SAlan Tull int of_fpga_bridge_get_to_list(struct device_node *np,
24021aeda95SAlan Tull struct fpga_image_info *info,
24121aeda95SAlan Tull struct list_head *bridge_list)
24221aeda95SAlan Tull {
24321aeda95SAlan Tull struct fpga_bridge *bridge;
24421aeda95SAlan Tull unsigned long flags;
24521aeda95SAlan Tull
24621aeda95SAlan Tull bridge = of_fpga_bridge_get(np, info);
24721aeda95SAlan Tull if (IS_ERR(bridge))
24821aeda95SAlan Tull return PTR_ERR(bridge);
24921aeda95SAlan Tull
25021aeda95SAlan Tull spin_lock_irqsave(&bridge_list_lock, flags);
25121aeda95SAlan Tull list_add(&bridge->node, bridge_list);
25221aeda95SAlan Tull spin_unlock_irqrestore(&bridge_list_lock, flags);
25321aeda95SAlan Tull
25421aeda95SAlan Tull return 0;
25521aeda95SAlan Tull }
2569c1c4b27SAlan Tull EXPORT_SYMBOL_GPL(of_fpga_bridge_get_to_list);
2579c1c4b27SAlan Tull
2589c1c4b27SAlan Tull /**
2599c1c4b27SAlan Tull * fpga_bridge_get_to_list - given device, get a bridge, add it to a list
2609c1c4b27SAlan Tull *
2619c1c4b27SAlan Tull * @dev: FPGA bridge device
2629c1c4b27SAlan Tull * @info: fpga image specific information
2639c1c4b27SAlan Tull * @bridge_list: list of FPGA bridges
2649c1c4b27SAlan Tull *
2650a05cdf1SNavin Sankar Velliangiri * Get an exclusive reference to the bridge and it to the list.
2669c1c4b27SAlan Tull *
2678e665c9cSMarco Pagani * Return: 0 for success, error code from fpga_bridge_get() otherwise.
2689c1c4b27SAlan Tull */
fpga_bridge_get_to_list(struct device * dev,struct fpga_image_info * info,struct list_head * bridge_list)2699c1c4b27SAlan Tull int fpga_bridge_get_to_list(struct device *dev,
2709c1c4b27SAlan Tull struct fpga_image_info *info,
2719c1c4b27SAlan Tull struct list_head *bridge_list)
2729c1c4b27SAlan Tull {
2739c1c4b27SAlan Tull struct fpga_bridge *bridge;
2749c1c4b27SAlan Tull unsigned long flags;
2759c1c4b27SAlan Tull
2769c1c4b27SAlan Tull bridge = fpga_bridge_get(dev, info);
2779c1c4b27SAlan Tull if (IS_ERR(bridge))
2789c1c4b27SAlan Tull return PTR_ERR(bridge);
2799c1c4b27SAlan Tull
2809c1c4b27SAlan Tull spin_lock_irqsave(&bridge_list_lock, flags);
2819c1c4b27SAlan Tull list_add(&bridge->node, bridge_list);
2829c1c4b27SAlan Tull spin_unlock_irqrestore(&bridge_list_lock, flags);
2839c1c4b27SAlan Tull
2849c1c4b27SAlan Tull return 0;
2859c1c4b27SAlan Tull }
28621aeda95SAlan Tull EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
28721aeda95SAlan Tull
name_show(struct device * dev,struct device_attribute * attr,char * buf)28821aeda95SAlan Tull static ssize_t name_show(struct device *dev,
28921aeda95SAlan Tull struct device_attribute *attr, char *buf)
29021aeda95SAlan Tull {
29121aeda95SAlan Tull struct fpga_bridge *bridge = to_fpga_bridge(dev);
29221aeda95SAlan Tull
29321aeda95SAlan Tull return sprintf(buf, "%s\n", bridge->name);
29421aeda95SAlan Tull }
29521aeda95SAlan Tull
state_show(struct device * dev,struct device_attribute * attr,char * buf)29621aeda95SAlan Tull static ssize_t state_show(struct device *dev,
29721aeda95SAlan Tull struct device_attribute *attr, char *buf)
29821aeda95SAlan Tull {
29921aeda95SAlan Tull struct fpga_bridge *bridge = to_fpga_bridge(dev);
30048ca6e5fSMarco Pagani int state = 1;
30121aeda95SAlan Tull
30248ca6e5fSMarco Pagani if (bridge->br_ops && bridge->br_ops->enable_show) {
30348ca6e5fSMarco Pagani state = bridge->br_ops->enable_show(bridge);
30448ca6e5fSMarco Pagani if (state < 0)
30548ca6e5fSMarco Pagani return state;
30648ca6e5fSMarco Pagani }
30721aeda95SAlan Tull
30848ca6e5fSMarco Pagani return sysfs_emit(buf, "%s\n", state ? "enabled" : "disabled");
30921aeda95SAlan Tull }
31021aeda95SAlan Tull
31121aeda95SAlan Tull static DEVICE_ATTR_RO(name);
31221aeda95SAlan Tull static DEVICE_ATTR_RO(state);
31321aeda95SAlan Tull
31421aeda95SAlan Tull static struct attribute *fpga_bridge_attrs[] = {
31521aeda95SAlan Tull &dev_attr_name.attr,
31621aeda95SAlan Tull &dev_attr_state.attr,
31721aeda95SAlan Tull NULL,
31821aeda95SAlan Tull };
31921aeda95SAlan Tull ATTRIBUTE_GROUPS(fpga_bridge);
32021aeda95SAlan Tull
32121aeda95SAlan Tull /**
322*d7c4081cSMarco Pagani * __fpga_bridge_register - create and register an FPGA Bridge device
323ceb8ab3cSRuss Weight * @parent: FPGA bridge device from pdev
32421aeda95SAlan Tull * @name: FPGA bridge name
32521aeda95SAlan Tull * @br_ops: pointer to structure of fpga bridge ops
32621aeda95SAlan Tull * @priv: FPGA bridge private data
327*d7c4081cSMarco Pagani * @owner: owner module containing the br_ops
32821aeda95SAlan Tull *
3290d70af3cSRuss Weight * Return: struct fpga_bridge pointer or ERR_PTR()
33021aeda95SAlan Tull */
3310d70af3cSRuss Weight struct fpga_bridge *
__fpga_bridge_register(struct device * parent,const char * name,const struct fpga_bridge_ops * br_ops,void * priv,struct module * owner)332*d7c4081cSMarco Pagani __fpga_bridge_register(struct device *parent, const char *name,
333371cd1b1SAlan Tull const struct fpga_bridge_ops *br_ops,
334*d7c4081cSMarco Pagani void *priv, struct module *owner)
33521aeda95SAlan Tull {
33621aeda95SAlan Tull struct fpga_bridge *bridge;
337d3fbd739STom Rix int id, ret;
33821aeda95SAlan Tull
3390d70af3cSRuss Weight if (!br_ops) {
3400d70af3cSRuss Weight dev_err(parent, "Attempt to register without fpga_bridge_ops\n");
3410d70af3cSRuss Weight return ERR_PTR(-EINVAL);
3420d70af3cSRuss Weight }
3430d70af3cSRuss Weight
34421aeda95SAlan Tull if (!name || !strlen(name)) {
345ceb8ab3cSRuss Weight dev_err(parent, "Attempt to register with no name!\n");
3460d70af3cSRuss Weight return ERR_PTR(-EINVAL);
34721aeda95SAlan Tull }
34821aeda95SAlan Tull
34921aeda95SAlan Tull bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
35021aeda95SAlan Tull if (!bridge)
3510d70af3cSRuss Weight return ERR_PTR(-ENOMEM);
35221aeda95SAlan Tull
353a5e3d775Skeliu id = ida_alloc(&fpga_bridge_ida, GFP_KERNEL);
3540d70af3cSRuss Weight if (id < 0) {
3550d70af3cSRuss Weight ret = id;
35621aeda95SAlan Tull goto error_kfree;
3570d70af3cSRuss Weight }
35821aeda95SAlan Tull
35921aeda95SAlan Tull mutex_init(&bridge->mutex);
36021aeda95SAlan Tull INIT_LIST_HEAD(&bridge->node);
36121aeda95SAlan Tull
36221aeda95SAlan Tull bridge->name = name;
36321aeda95SAlan Tull bridge->br_ops = br_ops;
364*d7c4081cSMarco Pagani bridge->br_ops_owner = owner;
36521aeda95SAlan Tull bridge->priv = priv;
36621aeda95SAlan Tull
367845089bbSAlan Tull bridge->dev.groups = br_ops->groups;
3687bb2d219SIvan Orlov bridge->dev.class = &fpga_bridge_class;
369ceb8ab3cSRuss Weight bridge->dev.parent = parent;
370ceb8ab3cSRuss Weight bridge->dev.of_node = parent->of_node;
37121aeda95SAlan Tull bridge->dev.id = id;
37221aeda95SAlan Tull
37321aeda95SAlan Tull ret = dev_set_name(&bridge->dev, "br%d", id);
37421aeda95SAlan Tull if (ret)
37521aeda95SAlan Tull goto error_device;
37621aeda95SAlan Tull
3770d70af3cSRuss Weight ret = device_register(&bridge->dev);
3780d70af3cSRuss Weight if (ret) {
3790d70af3cSRuss Weight put_device(&bridge->dev);
3800d70af3cSRuss Weight return ERR_PTR(ret);
3810d70af3cSRuss Weight }
3820d70af3cSRuss Weight
383dc70eb86SAlexis Lothoré of_platform_populate(bridge->dev.of_node, NULL, NULL, &bridge->dev);
384dc70eb86SAlexis Lothoré
385371cd1b1SAlan Tull return bridge;
38621aeda95SAlan Tull
38721aeda95SAlan Tull error_device:
388a5e3d775Skeliu ida_free(&fpga_bridge_ida, id);
38921aeda95SAlan Tull error_kfree:
39021aeda95SAlan Tull kfree(bridge);
39121aeda95SAlan Tull
3920d70af3cSRuss Weight return ERR_PTR(ret);
39321aeda95SAlan Tull }
394*d7c4081cSMarco Pagani EXPORT_SYMBOL_GPL(__fpga_bridge_register);
39521aeda95SAlan Tull
39621aeda95SAlan Tull /**
397e7555cf6STom Rix * fpga_bridge_unregister - unregister an FPGA bridge
398213befe0SAlan Tull *
399213befe0SAlan Tull * @bridge: FPGA bridge struct
400213befe0SAlan Tull *
401e7555cf6STom Rix * This function is intended for use in an FPGA bridge driver's remove function.
40221aeda95SAlan Tull */
fpga_bridge_unregister(struct fpga_bridge * bridge)403371cd1b1SAlan Tull void fpga_bridge_unregister(struct fpga_bridge *bridge)
40421aeda95SAlan Tull {
40521aeda95SAlan Tull /*
40621aeda95SAlan Tull * If the low level driver provides a method for putting bridge into
40721aeda95SAlan Tull * a desired state upon unregister, do it.
40821aeda95SAlan Tull */
40921aeda95SAlan Tull if (bridge->br_ops && bridge->br_ops->fpga_bridge_remove)
41021aeda95SAlan Tull bridge->br_ops->fpga_bridge_remove(bridge);
41121aeda95SAlan Tull
41221aeda95SAlan Tull device_unregister(&bridge->dev);
41321aeda95SAlan Tull }
41421aeda95SAlan Tull EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
41521aeda95SAlan Tull
fpga_bridge_dev_release(struct device * dev)41621aeda95SAlan Tull static void fpga_bridge_dev_release(struct device *dev)
41721aeda95SAlan Tull {
4180d70af3cSRuss Weight struct fpga_bridge *bridge = to_fpga_bridge(dev);
4190d70af3cSRuss Weight
420a5e3d775Skeliu ida_free(&fpga_bridge_ida, bridge->dev.id);
4210d70af3cSRuss Weight kfree(bridge);
42221aeda95SAlan Tull }
42321aeda95SAlan Tull
4247bb2d219SIvan Orlov static const struct class fpga_bridge_class = {
4257bb2d219SIvan Orlov .name = "fpga_bridge",
4267bb2d219SIvan Orlov .dev_groups = fpga_bridge_groups,
4277bb2d219SIvan Orlov .dev_release = fpga_bridge_dev_release,
4287bb2d219SIvan Orlov };
4297bb2d219SIvan Orlov
fpga_bridge_dev_init(void)43021aeda95SAlan Tull static int __init fpga_bridge_dev_init(void)
43121aeda95SAlan Tull {
4327bb2d219SIvan Orlov return class_register(&fpga_bridge_class);
43321aeda95SAlan Tull }
43421aeda95SAlan Tull
fpga_bridge_dev_exit(void)43521aeda95SAlan Tull static void __exit fpga_bridge_dev_exit(void)
43621aeda95SAlan Tull {
4377bb2d219SIvan Orlov class_unregister(&fpga_bridge_class);
43821aeda95SAlan Tull ida_destroy(&fpga_bridge_ida);
43921aeda95SAlan Tull }
44021aeda95SAlan Tull
44121aeda95SAlan Tull MODULE_DESCRIPTION("FPGA Bridge Driver");
4429c1c4b27SAlan Tull MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
44321aeda95SAlan Tull MODULE_LICENSE("GPL v2");
44421aeda95SAlan Tull
44521aeda95SAlan Tull subsys_initcall(fpga_bridge_dev_init);
44621aeda95SAlan Tull module_exit(fpga_bridge_dev_exit);
447