FPGA Manager changes for 5.17-rc1
Russ' patches rework the way we register FPGA managers, regions and bridges by simplifying the functions into a single register call. Nathan's patch addresses an unused variable warning that was introduced by Russ' patches. Yang's patch addresses a kernel doc warning. All patches have been reviewed on the mailing list, and have been in the last few linux-next releases (as part of our for-next branch) without issues. Signed-off-by: Moritz Fischer <mdf@kernel.org> -----BEGIN PGP SIGNATURE----- iIUEABYIAC0WIQSdhnt2PwibB65UG0C3mJX/Vsn7uQUCYbz4vQ8cbWRmQGtlcm5l bC5vcmcACgkQt5iV/1bJ+7mdsAEA1wiVjcmpJZGb+3HoMxdLIJGQ+BV341eXpDp3 AYS9Hx4A/i8jZ4YqrFe+v9IgXe6Arq2ePzIW/FpacwijobMBiHQE =S1TU -----END PGP SIGNATURE----- Merge tag 'fpga-for-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga into char-misc-next Moritz writes: FPGA Manager changes for 5.17-rc1 Russ' patches rework the way we register FPGA managers, regions and bridges by simplifying the functions into a single register call. Nathan's patch addresses an unused variable warning that was introduced by Russ' patches. Yang's patch addresses a kernel doc warning. All patches have been reviewed on the mailing list, and have been in the last few linux-next releases (as part of our for-next branch) without issues. Signed-off-by: Moritz Fischer <mdf@kernel.org> * tag 'fpga-for-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga: fpga: region: fix kernel-doc fpga: stratix10-soc: Do not use ret uninitialized in s10_probe() fpga: region: Use standard dev_release for class driver fpga: bridge: Use standard dev_release for class driver fpga: mgr: Use standard dev_release for class driver
This commit is contained in:
Коммит
a4c1aaf97b
|
@ -6,8 +6,7 @@ API to implement a new FPGA bridge
|
|||
|
||||
* struct fpga_bridge - The FPGA Bridge structure
|
||||
* struct fpga_bridge_ops - Low level Bridge driver ops
|
||||
* devm_fpga_bridge_create() - Allocate and init a bridge struct
|
||||
* fpga_bridge_register() - Register a bridge
|
||||
* fpga_bridge_register() - Create and register a bridge
|
||||
* fpga_bridge_unregister() - Unregister a bridge
|
||||
|
||||
.. kernel-doc:: include/linux/fpga/fpga-bridge.h
|
||||
|
@ -16,9 +15,6 @@ API to implement a new FPGA bridge
|
|||
.. kernel-doc:: include/linux/fpga/fpga-bridge.h
|
||||
:functions: fpga_bridge_ops
|
||||
|
||||
.. kernel-doc:: drivers/fpga/fpga-bridge.c
|
||||
:functions: devm_fpga_bridge_create
|
||||
|
||||
.. kernel-doc:: drivers/fpga/fpga-bridge.c
|
||||
:functions: fpga_bridge_register
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ How to support a new FPGA device
|
|||
--------------------------------
|
||||
|
||||
To add another FPGA manager, write a driver that implements a set of ops. The
|
||||
probe function calls fpga_mgr_register(), such as::
|
||||
probe function calls fpga_mgr_register() or fpga_mgr_register_full(), such as::
|
||||
|
||||
static const struct fpga_manager_ops socfpga_fpga_ops = {
|
||||
.write_init = socfpga_fpga_ops_configure_init,
|
||||
|
@ -49,14 +49,14 @@ probe function calls fpga_mgr_register(), such as::
|
|||
* them in priv
|
||||
*/
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager",
|
||||
&socfpga_fpga_ops, priv);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
mgr = fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
|
||||
&socfpga_fpga_ops, priv);
|
||||
if (IS_ERR(mgr))
|
||||
return PTR_ERR(mgr);
|
||||
|
||||
platform_set_drvdata(pdev, mgr);
|
||||
|
||||
return fpga_mgr_register(mgr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int socfpga_fpga_remove(struct platform_device *pdev)
|
||||
|
@ -68,6 +68,11 @@ probe function calls fpga_mgr_register(), such as::
|
|||
return 0;
|
||||
}
|
||||
|
||||
Alternatively, the probe function could call one of the resource managed
|
||||
register functions, devm_fpga_mgr_register() or devm_fpga_mgr_register_full().
|
||||
When these functions are used, the parameter syntax is the same, but the call
|
||||
to fpga_mgr_unregister() should be removed. In the above example, the
|
||||
socfpga_fpga_remove() function would not be required.
|
||||
|
||||
The ops will implement whatever device specific register writes are needed to
|
||||
do the programming sequence for this particular FPGA. These ops return 0 for
|
||||
|
@ -104,8 +109,14 @@ API for implementing a new FPGA Manager driver
|
|||
* ``fpga_mgr_states`` - Values for :c:expr:`fpga_manager->state`.
|
||||
* struct fpga_manager - the FPGA manager struct
|
||||
* struct fpga_manager_ops - Low level FPGA manager driver ops
|
||||
* devm_fpga_mgr_create() - Allocate and init a manager struct
|
||||
* fpga_mgr_register() - Register an FPGA manager
|
||||
* struct fpga_manager_info - Parameter structure for fpga_mgr_register_full()
|
||||
* fpga_mgr_register_full() - Create and register an FPGA manager using the
|
||||
fpga_mgr_info structure to provide the full flexibility of options
|
||||
* fpga_mgr_register() - Create and register an FPGA manager using standard
|
||||
arguments
|
||||
* devm_fpga_mgr_register_full() - Resource managed version of
|
||||
fpga_mgr_register_full()
|
||||
* devm_fpga_mgr_register() - Resource managed version of fpga_mgr_register()
|
||||
* fpga_mgr_unregister() - Unregister an FPGA manager
|
||||
|
||||
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
|
||||
|
@ -117,11 +128,20 @@ API for implementing a new FPGA Manager driver
|
|||
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
|
||||
:functions: fpga_manager_ops
|
||||
|
||||
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
|
||||
:functions: fpga_manager_info
|
||||
|
||||
.. kernel-doc:: drivers/fpga/fpga-mgr.c
|
||||
:functions: devm_fpga_mgr_create
|
||||
:functions: fpga_mgr_register_full
|
||||
|
||||
.. kernel-doc:: drivers/fpga/fpga-mgr.c
|
||||
:functions: fpga_mgr_register
|
||||
|
||||
.. kernel-doc:: drivers/fpga/fpga-mgr.c
|
||||
:functions: devm_fpga_mgr_register_full
|
||||
|
||||
.. kernel-doc:: drivers/fpga/fpga-mgr.c
|
||||
:functions: devm_fpga_mgr_register
|
||||
|
||||
.. kernel-doc:: drivers/fpga/fpga-mgr.c
|
||||
:functions: fpga_mgr_unregister
|
||||
|
|
|
@ -46,8 +46,11 @@ API to add a new FPGA region
|
|||
----------------------------
|
||||
|
||||
* struct fpga_region - The FPGA region struct
|
||||
* devm_fpga_region_create() - Allocate and init a region struct
|
||||
* fpga_region_register() - Register an FPGA region
|
||||
* struct fpga_region_info - Parameter structure for fpga_region_register_full()
|
||||
* fpga_region_register_full() - Create and register an FPGA region using the
|
||||
fpga_region_info structure to provide the full flexibility of options
|
||||
* fpga_region_register() - Create and register an FPGA region using standard
|
||||
arguments
|
||||
* fpga_region_unregister() - Unregister an FPGA region
|
||||
|
||||
The FPGA region's probe function will need to get a reference to the FPGA
|
||||
|
@ -75,8 +78,11 @@ following APIs to handle building or tearing down that list.
|
|||
.. kernel-doc:: include/linux/fpga/fpga-region.h
|
||||
:functions: fpga_region
|
||||
|
||||
.. kernel-doc:: include/linux/fpga/fpga-region.h
|
||||
:functions: fpga_region_info
|
||||
|
||||
.. kernel-doc:: drivers/fpga/fpga-region.c
|
||||
:functions: devm_fpga_region_create
|
||||
:functions: fpga_region_register_full
|
||||
|
||||
.. kernel-doc:: drivers/fpga/fpga-region.c
|
||||
:functions: fpga_region_register
|
||||
|
|
|
@ -652,19 +652,15 @@ static int altera_cvp_probe(struct pci_dev *pdev,
|
|||
snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s",
|
||||
ALTERA_CVP_MGR_NAME, pci_name(pdev));
|
||||
|
||||
mgr = devm_fpga_mgr_create(&pdev->dev, conf->mgr_name,
|
||||
&altera_cvp_ops, conf);
|
||||
if (!mgr) {
|
||||
ret = -ENOMEM;
|
||||
mgr = fpga_mgr_register(&pdev->dev, conf->mgr_name,
|
||||
&altera_cvp_ops, conf);
|
||||
if (IS_ERR(mgr)) {
|
||||
ret = PTR_ERR(mgr);
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, mgr);
|
||||
|
||||
ret = fpga_mgr_register(mgr);
|
||||
if (ret)
|
||||
goto err_unmap;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unmap:
|
||||
|
|
|
@ -121,17 +121,13 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
|
|||
/* Get f2s bridge configuration saved in handoff register */
|
||||
regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask);
|
||||
|
||||
br = devm_fpga_bridge_create(dev, F2S_BRIDGE_NAME,
|
||||
&altera_fpga2sdram_br_ops, priv);
|
||||
if (!br)
|
||||
return -ENOMEM;
|
||||
br = fpga_bridge_register(dev, F2S_BRIDGE_NAME,
|
||||
&altera_fpga2sdram_br_ops, priv);
|
||||
if (IS_ERR(br))
|
||||
return PTR_ERR(br);
|
||||
|
||||
platform_set_drvdata(pdev, br);
|
||||
|
||||
ret = fpga_bridge_register(br);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
|
||||
|
||||
if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
|
||||
|
|
|
@ -246,14 +246,14 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
|
|||
|
||||
priv->base_addr = base_addr;
|
||||
|
||||
br = devm_fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
|
||||
&altera_freeze_br_br_ops, priv);
|
||||
if (!br)
|
||||
return -ENOMEM;
|
||||
br = fpga_bridge_register(dev, FREEZE_BRIDGE_NAME,
|
||||
&altera_freeze_br_br_ops, priv);
|
||||
if (IS_ERR(br))
|
||||
return PTR_ERR(br);
|
||||
|
||||
platform_set_drvdata(pdev, br);
|
||||
|
||||
return fpga_bridge_register(br);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int altera_freeze_br_remove(struct platform_device *pdev)
|
||||
|
|
|
@ -180,19 +180,15 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
br = devm_fpga_bridge_create(dev, priv->name,
|
||||
&altera_hps2fpga_br_ops, priv);
|
||||
if (!br) {
|
||||
ret = -ENOMEM;
|
||||
br = fpga_bridge_register(dev, priv->name,
|
||||
&altera_hps2fpga_br_ops, priv);
|
||||
if (IS_ERR(br)) {
|
||||
ret = PTR_ERR(br);
|
||||
goto err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, br);
|
||||
|
||||
ret = fpga_bridge_register(br);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
|
|
@ -191,11 +191,8 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base)
|
|||
(val & ALT_PR_CSR_STATUS_MSK) >> ALT_PR_CSR_STATUS_SFT,
|
||||
(int)(val & ALT_PR_CSR_PR_START));
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
return devm_fpga_mgr_register(dev, mgr);
|
||||
mgr = devm_fpga_mgr_register(dev, dev_name(dev), &alt_pr_ops, priv);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(alt_pr_register);
|
||||
|
||||
|
|
|
@ -302,12 +302,9 @@ static int altera_ps_probe(struct spi_device *spi)
|
|||
snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s",
|
||||
dev_driver_string(&spi->dev), dev_name(&spi->dev));
|
||||
|
||||
mgr = devm_fpga_mgr_create(&spi->dev, conf->mgr_name,
|
||||
&altera_ps_ops, conf);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
return devm_fpga_mgr_register(&spi->dev, mgr);
|
||||
mgr = devm_fpga_mgr_register(&spi->dev, conf->mgr_name,
|
||||
&altera_ps_ops, conf);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
|
||||
static const struct spi_device_id altera_ps_spi_ids[] = {
|
||||
|
|
|
@ -68,14 +68,14 @@ static int fme_br_probe(struct platform_device *pdev)
|
|||
|
||||
priv->pdata = dev_get_platdata(dev);
|
||||
|
||||
br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge",
|
||||
&fme_bridge_ops, priv);
|
||||
if (!br)
|
||||
return -ENOMEM;
|
||||
br = fpga_bridge_register(dev, "DFL FPGA FME Bridge",
|
||||
&fme_bridge_ops, priv);
|
||||
if (IS_ERR(br))
|
||||
return PTR_ERR(br);
|
||||
|
||||
platform_set_drvdata(pdev, br);
|
||||
|
||||
return fpga_bridge_register(br);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fme_br_remove(struct platform_device *pdev)
|
||||
|
|
|
@ -276,7 +276,7 @@ static void fme_mgr_get_compat_id(void __iomem *fme_pr,
|
|||
static int fme_mgr_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct dfl_fme_mgr_pdata *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct fpga_compat_id *compat_id;
|
||||
struct fpga_manager_info info = { 0 };
|
||||
struct device *dev = &pdev->dev;
|
||||
struct fme_mgr_priv *priv;
|
||||
struct fpga_manager *mgr;
|
||||
|
@ -296,20 +296,16 @@ static int fme_mgr_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(priv->ioaddr);
|
||||
}
|
||||
|
||||
compat_id = devm_kzalloc(dev, sizeof(*compat_id), GFP_KERNEL);
|
||||
if (!compat_id)
|
||||
info.name = "DFL FME FPGA Manager";
|
||||
info.mops = &fme_mgr_ops;
|
||||
info.priv = priv;
|
||||
info.compat_id = devm_kzalloc(dev, sizeof(*info.compat_id), GFP_KERNEL);
|
||||
if (!info.compat_id)
|
||||
return -ENOMEM;
|
||||
|
||||
fme_mgr_get_compat_id(priv->ioaddr, compat_id);
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, "DFL FME FPGA Manager",
|
||||
&fme_mgr_ops, priv);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
mgr->compat_id = compat_id;
|
||||
|
||||
return devm_fpga_mgr_register(dev, mgr);
|
||||
fme_mgr_get_compat_id(priv->ioaddr, info.compat_id);
|
||||
mgr = devm_fpga_mgr_register_full(dev, &info);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
|
||||
static struct platform_driver fme_mgr_driver = {
|
||||
|
|
|
@ -30,6 +30,7 @@ static int fme_region_get_bridges(struct fpga_region *region)
|
|||
static int fme_region_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct dfl_fme_region_pdata *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct fpga_region_info info = { 0 };
|
||||
struct device *dev = &pdev->dev;
|
||||
struct fpga_region *region;
|
||||
struct fpga_manager *mgr;
|
||||
|
@ -39,20 +40,18 @@ static int fme_region_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(mgr))
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
region = devm_fpga_region_create(dev, mgr, fme_region_get_bridges);
|
||||
if (!region) {
|
||||
ret = -ENOMEM;
|
||||
info.mgr = mgr;
|
||||
info.compat_id = mgr->compat_id;
|
||||
info.get_bridges = fme_region_get_bridges;
|
||||
info.priv = pdata;
|
||||
region = fpga_region_register_full(dev, &info);
|
||||
if (IS_ERR(region)) {
|
||||
ret = PTR_ERR(region);
|
||||
goto eprobe_mgr_put;
|
||||
}
|
||||
|
||||
region->priv = pdata;
|
||||
region->compat_id = mgr->compat_id;
|
||||
platform_set_drvdata(pdev, region);
|
||||
|
||||
ret = fpga_region_register(region);
|
||||
if (ret)
|
||||
goto eprobe_mgr_put;
|
||||
|
||||
dev_dbg(dev, "DFL FME FPGA Region probed\n");
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1407,19 +1407,15 @@ dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info)
|
|||
if (!cdev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
cdev->region = devm_fpga_region_create(info->dev, NULL, NULL);
|
||||
if (!cdev->region) {
|
||||
ret = -ENOMEM;
|
||||
goto free_cdev_exit;
|
||||
}
|
||||
|
||||
cdev->parent = info->dev;
|
||||
mutex_init(&cdev->lock);
|
||||
INIT_LIST_HEAD(&cdev->port_dev_list);
|
||||
|
||||
ret = fpga_region_register(cdev->region);
|
||||
if (ret)
|
||||
cdev->region = fpga_region_register(info->dev, NULL, NULL);
|
||||
if (IS_ERR(cdev->region)) {
|
||||
ret = PTR_ERR(cdev->region);
|
||||
goto free_cdev_exit;
|
||||
}
|
||||
|
||||
/* create and init build info for enumeration */
|
||||
binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL);
|
||||
|
|
|
@ -312,36 +312,41 @@ static struct attribute *fpga_bridge_attrs[] = {
|
|||
ATTRIBUTE_GROUPS(fpga_bridge);
|
||||
|
||||
/**
|
||||
* fpga_bridge_create - create and initialize a struct fpga_bridge
|
||||
* fpga_bridge_register - create and register an FPGA Bridge device
|
||||
* @parent: FPGA bridge device from pdev
|
||||
* @name: FPGA bridge name
|
||||
* @br_ops: pointer to structure of fpga bridge ops
|
||||
* @priv: FPGA bridge private data
|
||||
*
|
||||
* The caller of this function is responsible for freeing the bridge with
|
||||
* fpga_bridge_free(). Using devm_fpga_bridge_create() instead is recommended.
|
||||
*
|
||||
* Return: struct fpga_bridge or NULL
|
||||
* Return: struct fpga_bridge pointer or ERR_PTR()
|
||||
*/
|
||||
struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name,
|
||||
const struct fpga_bridge_ops *br_ops,
|
||||
void *priv)
|
||||
struct fpga_bridge *
|
||||
fpga_bridge_register(struct device *parent, const char *name,
|
||||
const struct fpga_bridge_ops *br_ops,
|
||||
void *priv)
|
||||
{
|
||||
struct fpga_bridge *bridge;
|
||||
int id, ret;
|
||||
|
||||
if (!br_ops) {
|
||||
dev_err(parent, "Attempt to register without fpga_bridge_ops\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (!name || !strlen(name)) {
|
||||
dev_err(parent, "Attempt to register with no name!\n");
|
||||
return NULL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
|
||||
if (!bridge)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
|
||||
if (id < 0)
|
||||
if (id < 0) {
|
||||
ret = id;
|
||||
goto error_kfree;
|
||||
}
|
||||
|
||||
mutex_init(&bridge->mutex);
|
||||
INIT_LIST_HEAD(&bridge->node);
|
||||
|
@ -350,17 +355,23 @@ struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name,
|
|||
bridge->br_ops = br_ops;
|
||||
bridge->priv = priv;
|
||||
|
||||
device_initialize(&bridge->dev);
|
||||
bridge->dev.groups = br_ops->groups;
|
||||
bridge->dev.class = fpga_bridge_class;
|
||||
bridge->dev.parent = parent;
|
||||
bridge->dev.of_node = parent->of_node;
|
||||
bridge->dev.id = id;
|
||||
of_platform_populate(bridge->dev.of_node, NULL, NULL, &bridge->dev);
|
||||
|
||||
ret = dev_set_name(&bridge->dev, "br%d", id);
|
||||
if (ret)
|
||||
goto error_device;
|
||||
|
||||
ret = device_register(&bridge->dev);
|
||||
if (ret) {
|
||||
put_device(&bridge->dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return bridge;
|
||||
|
||||
error_device:
|
||||
|
@ -368,88 +379,7 @@ error_device:
|
|||
error_kfree:
|
||||
kfree(bridge);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_bridge_create);
|
||||
|
||||
/**
|
||||
* fpga_bridge_free - free an fpga bridge created by fpga_bridge_create()
|
||||
* @bridge: FPGA bridge struct
|
||||
*/
|
||||
void fpga_bridge_free(struct fpga_bridge *bridge)
|
||||
{
|
||||
ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
|
||||
kfree(bridge);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_bridge_free);
|
||||
|
||||
static void devm_fpga_bridge_release(struct device *dev, void *res)
|
||||
{
|
||||
struct fpga_bridge *bridge = *(struct fpga_bridge **)res;
|
||||
|
||||
fpga_bridge_free(bridge);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_fpga_bridge_create - create and init a managed struct fpga_bridge
|
||||
* @parent: FPGA bridge device from pdev
|
||||
* @name: FPGA bridge name
|
||||
* @br_ops: pointer to structure of fpga bridge ops
|
||||
* @priv: FPGA bridge private data
|
||||
*
|
||||
* This function is intended for use in an FPGA bridge driver's probe function.
|
||||
* After the bridge driver creates the struct with devm_fpga_bridge_create(), it
|
||||
* should register the bridge with fpga_bridge_register(). The bridge driver's
|
||||
* remove function should call fpga_bridge_unregister(). The bridge struct
|
||||
* allocated with this function will be freed automatically on driver detach.
|
||||
* This includes the case of a probe function returning error before calling
|
||||
* fpga_bridge_register(), the struct will still get cleaned up.
|
||||
*
|
||||
* Return: struct fpga_bridge or NULL
|
||||
*/
|
||||
struct fpga_bridge
|
||||
*devm_fpga_bridge_create(struct device *parent, const char *name,
|
||||
const struct fpga_bridge_ops *br_ops, void *priv)
|
||||
{
|
||||
struct fpga_bridge **ptr, *bridge;
|
||||
|
||||
ptr = devres_alloc(devm_fpga_bridge_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
bridge = fpga_bridge_create(parent, name, br_ops, priv);
|
||||
if (!bridge) {
|
||||
devres_free(ptr);
|
||||
} else {
|
||||
*ptr = bridge;
|
||||
devres_add(parent, ptr);
|
||||
}
|
||||
|
||||
return bridge;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_fpga_bridge_create);
|
||||
|
||||
/**
|
||||
* fpga_bridge_register - register an FPGA bridge
|
||||
*
|
||||
* @bridge: FPGA bridge struct
|
||||
*
|
||||
* Return: 0 for success, error code otherwise.
|
||||
*/
|
||||
int fpga_bridge_register(struct fpga_bridge *bridge)
|
||||
{
|
||||
struct device *dev = &bridge->dev;
|
||||
int ret;
|
||||
|
||||
ret = device_add(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||
|
||||
dev_info(dev->parent, "fpga bridge [%s] registered\n", bridge->name);
|
||||
|
||||
return 0;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_bridge_register);
|
||||
|
||||
|
@ -475,6 +405,10 @@ EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
|
|||
|
||||
static void fpga_bridge_dev_release(struct device *dev)
|
||||
{
|
||||
struct fpga_bridge *bridge = to_fpga_bridge(dev);
|
||||
|
||||
ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
|
||||
kfree(bridge);
|
||||
}
|
||||
|
||||
static int __init fpga_bridge_dev_init(void)
|
||||
|
|
|
@ -592,49 +592,49 @@ void fpga_mgr_unlock(struct fpga_manager *mgr)
|
|||
EXPORT_SYMBOL_GPL(fpga_mgr_unlock);
|
||||
|
||||
/**
|
||||
* fpga_mgr_create - create and initialize an FPGA manager struct
|
||||
* fpga_mgr_register_full - create and register an FPGA Manager device
|
||||
* @parent: fpga manager device from pdev
|
||||
* @name: fpga manager name
|
||||
* @mops: pointer to structure of fpga manager ops
|
||||
* @priv: fpga manager private data
|
||||
* @info: parameters for fpga manager
|
||||
*
|
||||
* The caller of this function is responsible for freeing the struct with
|
||||
* fpga_mgr_free(). Using devm_fpga_mgr_create() instead is recommended.
|
||||
* The caller of this function is responsible for calling fpga_mgr_unregister().
|
||||
* Using devm_fpga_mgr_register_full() instead is recommended.
|
||||
*
|
||||
* Return: pointer to struct fpga_manager or NULL
|
||||
* Return: pointer to struct fpga_manager pointer or ERR_PTR()
|
||||
*/
|
||||
struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name,
|
||||
const struct fpga_manager_ops *mops,
|
||||
void *priv)
|
||||
struct fpga_manager *
|
||||
fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info)
|
||||
{
|
||||
const struct fpga_manager_ops *mops = info->mops;
|
||||
struct fpga_manager *mgr;
|
||||
int id, ret;
|
||||
|
||||
if (!mops) {
|
||||
dev_err(parent, "Attempt to register without fpga_manager_ops\n");
|
||||
return NULL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (!name || !strlen(name)) {
|
||||
if (!info->name || !strlen(info->name)) {
|
||||
dev_err(parent, "Attempt to register with no name!\n");
|
||||
return NULL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
|
||||
if (!mgr)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
|
||||
if (id < 0)
|
||||
if (id < 0) {
|
||||
ret = id;
|
||||
goto error_kfree;
|
||||
}
|
||||
|
||||
mutex_init(&mgr->ref_mutex);
|
||||
|
||||
mgr->name = name;
|
||||
mgr->mops = mops;
|
||||
mgr->priv = priv;
|
||||
mgr->name = info->name;
|
||||
mgr->mops = info->mops;
|
||||
mgr->priv = info->priv;
|
||||
mgr->compat_id = info->compat_id;
|
||||
|
||||
device_initialize(&mgr->dev);
|
||||
mgr->dev.class = fpga_mgr_class;
|
||||
mgr->dev.groups = mops->groups;
|
||||
mgr->dev.parent = parent;
|
||||
|
@ -645,84 +645,6 @@ struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name,
|
|||
if (ret)
|
||||
goto error_device;
|
||||
|
||||
return mgr;
|
||||
|
||||
error_device:
|
||||
ida_simple_remove(&fpga_mgr_ida, id);
|
||||
error_kfree:
|
||||
kfree(mgr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_mgr_create);
|
||||
|
||||
/**
|
||||
* fpga_mgr_free - free an FPGA manager created with fpga_mgr_create()
|
||||
* @mgr: fpga manager struct
|
||||
*/
|
||||
void fpga_mgr_free(struct fpga_manager *mgr)
|
||||
{
|
||||
ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
|
||||
kfree(mgr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_mgr_free);
|
||||
|
||||
static void devm_fpga_mgr_release(struct device *dev, void *res)
|
||||
{
|
||||
struct fpga_mgr_devres *dr = res;
|
||||
|
||||
fpga_mgr_free(dr->mgr);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_fpga_mgr_create - create and initialize a managed FPGA manager struct
|
||||
* @parent: fpga manager device from pdev
|
||||
* @name: fpga manager name
|
||||
* @mops: pointer to structure of fpga manager ops
|
||||
* @priv: fpga manager private data
|
||||
*
|
||||
* This function is intended for use in an FPGA manager driver's probe function.
|
||||
* After the manager driver creates the manager struct with
|
||||
* devm_fpga_mgr_create(), it should register it with fpga_mgr_register(). The
|
||||
* manager driver's remove function should call fpga_mgr_unregister(). The
|
||||
* manager struct allocated with this function will be freed automatically on
|
||||
* driver detach. This includes the case of a probe function returning error
|
||||
* before calling fpga_mgr_register(), the struct will still get cleaned up.
|
||||
*
|
||||
* Return: pointer to struct fpga_manager or NULL
|
||||
*/
|
||||
struct fpga_manager *devm_fpga_mgr_create(struct device *parent, const char *name,
|
||||
const struct fpga_manager_ops *mops,
|
||||
void *priv)
|
||||
{
|
||||
struct fpga_mgr_devres *dr;
|
||||
|
||||
dr = devres_alloc(devm_fpga_mgr_release, sizeof(*dr), GFP_KERNEL);
|
||||
if (!dr)
|
||||
return NULL;
|
||||
|
||||
dr->mgr = fpga_mgr_create(parent, name, mops, priv);
|
||||
if (!dr->mgr) {
|
||||
devres_free(dr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
devres_add(parent, dr);
|
||||
|
||||
return dr->mgr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_fpga_mgr_create);
|
||||
|
||||
/**
|
||||
* fpga_mgr_register - register an FPGA manager
|
||||
* @mgr: fpga manager struct
|
||||
*
|
||||
* Return: 0 on success, negative error code otherwise.
|
||||
*/
|
||||
int fpga_mgr_register(struct fpga_manager *mgr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Initialize framework state by requesting low level driver read state
|
||||
* from device. FPGA may be in reset mode or may have been programmed
|
||||
|
@ -730,18 +652,49 @@ int fpga_mgr_register(struct fpga_manager *mgr)
|
|||
*/
|
||||
mgr->state = fpga_mgr_state(mgr);
|
||||
|
||||
ret = device_add(&mgr->dev);
|
||||
if (ret)
|
||||
goto error_device;
|
||||
ret = device_register(&mgr->dev);
|
||||
if (ret) {
|
||||
put_device(&mgr->dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
dev_info(&mgr->dev, "%s registered\n", mgr->name);
|
||||
|
||||
return 0;
|
||||
return mgr;
|
||||
|
||||
error_device:
|
||||
ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
|
||||
ida_simple_remove(&fpga_mgr_ida, id);
|
||||
error_kfree:
|
||||
kfree(mgr);
|
||||
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_mgr_register_full);
|
||||
|
||||
/**
|
||||
* fpga_mgr_register - create and register an FPGA Manager device
|
||||
* @parent: fpga manager device from pdev
|
||||
* @name: fpga manager name
|
||||
* @mops: pointer to structure of fpga manager ops
|
||||
* @priv: fpga manager private data
|
||||
*
|
||||
* The caller of this function is responsible for calling fpga_mgr_unregister().
|
||||
* Using devm_fpga_mgr_register() instead is recommended. This simple
|
||||
* version of the register function should be sufficient for most users. The
|
||||
* fpga_mgr_register_full() function is available for users that need to pass
|
||||
* additional, optional parameters.
|
||||
*
|
||||
* Return: pointer to struct fpga_manager pointer or ERR_PTR()
|
||||
*/
|
||||
struct fpga_manager *
|
||||
fpga_mgr_register(struct device *parent, const char *name,
|
||||
const struct fpga_manager_ops *mops, void *priv)
|
||||
{
|
||||
struct fpga_manager_info info = { 0 };
|
||||
|
||||
info.name = name;
|
||||
info.mops = mops;
|
||||
info.priv = priv;
|
||||
|
||||
return fpga_mgr_register_full(parent, &info);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_mgr_register);
|
||||
|
||||
|
@ -765,14 +718,6 @@ void fpga_mgr_unregister(struct fpga_manager *mgr)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_mgr_unregister);
|
||||
|
||||
static int fpga_mgr_devres_match(struct device *dev, void *res,
|
||||
void *match_data)
|
||||
{
|
||||
struct fpga_mgr_devres *dr = res;
|
||||
|
||||
return match_data == dr->mgr;
|
||||
}
|
||||
|
||||
static void devm_fpga_mgr_unregister(struct device *dev, void *res)
|
||||
{
|
||||
struct fpga_mgr_devres *dr = res;
|
||||
|
@ -781,45 +726,67 @@ static void devm_fpga_mgr_unregister(struct device *dev, void *res)
|
|||
}
|
||||
|
||||
/**
|
||||
* devm_fpga_mgr_register - resource managed variant of fpga_mgr_register()
|
||||
* @dev: managing device for this FPGA manager
|
||||
* @mgr: fpga manager struct
|
||||
* devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register()
|
||||
* @parent: fpga manager device from pdev
|
||||
* @info: parameters for fpga manager
|
||||
*
|
||||
* This is the devres variant of fpga_mgr_register() for which the unregister
|
||||
* This is the devres variant of fpga_mgr_register_full() for which the unregister
|
||||
* function will be called automatically when the managing device is detached.
|
||||
*/
|
||||
int devm_fpga_mgr_register(struct device *dev, struct fpga_manager *mgr)
|
||||
struct fpga_manager *
|
||||
devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info)
|
||||
{
|
||||
struct fpga_mgr_devres *dr;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Make sure that the struct fpga_manager * that is passed in is
|
||||
* managed itself.
|
||||
*/
|
||||
if (WARN_ON(!devres_find(dev, devm_fpga_mgr_release,
|
||||
fpga_mgr_devres_match, mgr)))
|
||||
return -EINVAL;
|
||||
struct fpga_manager *mgr;
|
||||
|
||||
dr = devres_alloc(devm_fpga_mgr_unregister, sizeof(*dr), GFP_KERNEL);
|
||||
if (!dr)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = fpga_mgr_register(mgr);
|
||||
if (ret) {
|
||||
mgr = fpga_mgr_register_full(parent, info);
|
||||
if (IS_ERR(mgr)) {
|
||||
devres_free(dr);
|
||||
return ret;
|
||||
return mgr;
|
||||
}
|
||||
|
||||
dr->mgr = mgr;
|
||||
devres_add(dev, dr);
|
||||
devres_add(parent, dr);
|
||||
|
||||
return 0;
|
||||
return mgr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full);
|
||||
|
||||
/**
|
||||
* devm_fpga_mgr_register - resource managed variant of fpga_mgr_register()
|
||||
* @parent: fpga manager device from pdev
|
||||
* @name: fpga manager name
|
||||
* @mops: pointer to structure of fpga manager ops
|
||||
* @priv: fpga manager private data
|
||||
*
|
||||
* This is the devres variant of fpga_mgr_register() for which the
|
||||
* unregister function will be called automatically when the managing
|
||||
* device is detached.
|
||||
*/
|
||||
struct fpga_manager *
|
||||
devm_fpga_mgr_register(struct device *parent, const char *name,
|
||||
const struct fpga_manager_ops *mops, void *priv)
|
||||
{
|
||||
struct fpga_manager_info info = { 0 };
|
||||
|
||||
info.name = name;
|
||||
info.mops = mops;
|
||||
info.priv = priv;
|
||||
|
||||
return devm_fpga_mgr_register_full(parent, &info);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_fpga_mgr_register);
|
||||
|
||||
static void fpga_mgr_dev_release(struct device *dev)
|
||||
{
|
||||
struct fpga_manager *mgr = to_fpga_manager(dev);
|
||||
|
||||
ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
|
||||
kfree(mgr);
|
||||
}
|
||||
|
||||
static int __init fpga_mgr_class_init(void)
|
||||
|
|
|
@ -180,39 +180,42 @@ static struct attribute *fpga_region_attrs[] = {
|
|||
ATTRIBUTE_GROUPS(fpga_region);
|
||||
|
||||
/**
|
||||
* fpga_region_create - alloc and init a struct fpga_region
|
||||
* fpga_region_register_full - create and register an FPGA Region device
|
||||
* @parent: device parent
|
||||
* @mgr: manager that programs this region
|
||||
* @get_bridges: optional function to get bridges to a list
|
||||
* @info: parameters for FPGA Region
|
||||
*
|
||||
* The caller of this function is responsible for freeing the resulting region
|
||||
* struct with fpga_region_free(). Using devm_fpga_region_create() instead is
|
||||
* recommended.
|
||||
*
|
||||
* Return: struct fpga_region or NULL
|
||||
* Return: struct fpga_region or ERR_PTR()
|
||||
*/
|
||||
struct fpga_region
|
||||
*fpga_region_create(struct device *parent,
|
||||
struct fpga_manager *mgr,
|
||||
int (*get_bridges)(struct fpga_region *))
|
||||
struct fpga_region *
|
||||
fpga_region_register_full(struct device *parent, const struct fpga_region_info *info)
|
||||
{
|
||||
struct fpga_region *region;
|
||||
int id, ret = 0;
|
||||
|
||||
if (!info) {
|
||||
dev_err(parent,
|
||||
"Attempt to register without required info structure\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
region = kzalloc(sizeof(*region), GFP_KERNEL);
|
||||
if (!region)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
|
||||
if (id < 0)
|
||||
if (id < 0) {
|
||||
ret = id;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
region->mgr = info->mgr;
|
||||
region->compat_id = info->compat_id;
|
||||
region->priv = info->priv;
|
||||
region->get_bridges = info->get_bridges;
|
||||
|
||||
region->mgr = mgr;
|
||||
region->get_bridges = get_bridges;
|
||||
mutex_init(®ion->mutex);
|
||||
INIT_LIST_HEAD(®ion->bridge_list);
|
||||
|
||||
device_initialize(®ion->dev);
|
||||
region->dev.class = fpga_region_class;
|
||||
region->dev.parent = parent;
|
||||
region->dev.of_node = parent->of_node;
|
||||
|
@ -222,6 +225,12 @@ struct fpga_region
|
|||
if (ret)
|
||||
goto err_remove;
|
||||
|
||||
ret = device_register(®ion->dev);
|
||||
if (ret) {
|
||||
put_device(®ion->dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return region;
|
||||
|
||||
err_remove:
|
||||
|
@ -229,76 +238,32 @@ err_remove:
|
|||
err_free:
|
||||
kfree(region);
|
||||
|
||||
return NULL;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_region_create);
|
||||
EXPORT_SYMBOL_GPL(fpga_region_register_full);
|
||||
|
||||
/**
|
||||
* fpga_region_free - free an FPGA region created by fpga_region_create()
|
||||
* @region: FPGA region
|
||||
*/
|
||||
void fpga_region_free(struct fpga_region *region)
|
||||
{
|
||||
ida_simple_remove(&fpga_region_ida, region->dev.id);
|
||||
kfree(region);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_region_free);
|
||||
|
||||
static void devm_fpga_region_release(struct device *dev, void *res)
|
||||
{
|
||||
struct fpga_region *region = *(struct fpga_region **)res;
|
||||
|
||||
fpga_region_free(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_fpga_region_create - create and initialize a managed FPGA region struct
|
||||
* fpga_region_register - create and register an FPGA Region device
|
||||
* @parent: device parent
|
||||
* @mgr: manager that programs this region
|
||||
* @get_bridges: optional function to get bridges to a list
|
||||
*
|
||||
* This function is intended for use in an FPGA region driver's probe function.
|
||||
* After the region driver creates the region struct with
|
||||
* devm_fpga_region_create(), it should register it with fpga_region_register().
|
||||
* The region driver's remove function should call fpga_region_unregister().
|
||||
* The region struct allocated with this function will be freed automatically on
|
||||
* driver detach. This includes the case of a probe function returning error
|
||||
* before calling fpga_region_register(), the struct will still get cleaned up.
|
||||
* This simple version of the register function should be sufficient for most users.
|
||||
* The fpga_region_register_full() function is available for users that need to
|
||||
* pass additional, optional parameters.
|
||||
*
|
||||
* Return: struct fpga_region or NULL
|
||||
* Return: struct fpga_region or ERR_PTR()
|
||||
*/
|
||||
struct fpga_region
|
||||
*devm_fpga_region_create(struct device *parent,
|
||||
struct fpga_manager *mgr,
|
||||
int (*get_bridges)(struct fpga_region *))
|
||||
struct fpga_region *
|
||||
fpga_region_register(struct device *parent, struct fpga_manager *mgr,
|
||||
int (*get_bridges)(struct fpga_region *))
|
||||
{
|
||||
struct fpga_region **ptr, *region;
|
||||
struct fpga_region_info info = { 0 };
|
||||
|
||||
ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
info.mgr = mgr;
|
||||
info.get_bridges = get_bridges;
|
||||
|
||||
region = fpga_region_create(parent, mgr, get_bridges);
|
||||
if (!region) {
|
||||
devres_free(ptr);
|
||||
} else {
|
||||
*ptr = region;
|
||||
devres_add(parent, ptr);
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_fpga_region_create);
|
||||
|
||||
/**
|
||||
* fpga_region_register - register an FPGA region
|
||||
* @region: FPGA region
|
||||
*
|
||||
* Return: 0 or -errno
|
||||
*/
|
||||
int fpga_region_register(struct fpga_region *region)
|
||||
{
|
||||
return device_add(®ion->dev);
|
||||
return fpga_region_register_full(parent, &info);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fpga_region_register);
|
||||
|
||||
|
@ -316,6 +281,10 @@ EXPORT_SYMBOL_GPL(fpga_region_unregister);
|
|||
|
||||
static void fpga_region_dev_release(struct device *dev)
|
||||
{
|
||||
struct fpga_region *region = to_fpga_region(dev);
|
||||
|
||||
ida_simple_remove(&fpga_region_ida, region->dev.id);
|
||||
kfree(region);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -178,12 +178,9 @@ static int ice40_fpga_probe(struct spi_device *spi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, "Lattice iCE40 FPGA Manager",
|
||||
&ice40_fpga_ops, priv);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
return devm_fpga_mgr_register(dev, mgr);
|
||||
mgr = devm_fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager",
|
||||
&ice40_fpga_ops, priv);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
|
||||
static const struct of_device_id ice40_fpga_of_match[] = {
|
||||
|
|
|
@ -370,12 +370,9 @@ static int machxo2_spi_probe(struct spi_device *spi)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, "Lattice MachXO2 SPI FPGA Manager",
|
||||
&machxo2_ops, spi);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
return devm_fpga_mgr_register(dev, mgr);
|
||||
mgr = devm_fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager",
|
||||
&machxo2_ops, spi);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
|
|
@ -405,16 +405,12 @@ static int of_fpga_region_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(mgr))
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
region = devm_fpga_region_create(dev, mgr, of_fpga_region_get_bridges);
|
||||
if (!region) {
|
||||
ret = -ENOMEM;
|
||||
region = fpga_region_register(dev, mgr, of_fpga_region_get_bridges);
|
||||
if (IS_ERR(region)) {
|
||||
ret = PTR_ERR(region);
|
||||
goto eprobe_mgr_put;
|
||||
}
|
||||
|
||||
ret = fpga_region_register(region);
|
||||
if (ret)
|
||||
goto eprobe_mgr_put;
|
||||
|
||||
of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev);
|
||||
platform_set_drvdata(pdev, region);
|
||||
|
||||
|
@ -448,7 +444,7 @@ static struct platform_driver of_fpga_region_driver = {
|
|||
};
|
||||
|
||||
/**
|
||||
* fpga_region_init - init function for fpga_region class
|
||||
* of_fpga_region_init - init function for fpga_region class
|
||||
* Creates the fpga_region class and registers a reconfig notifier.
|
||||
*/
|
||||
static int __init of_fpga_region_init(void)
|
||||
|
|
|
@ -508,19 +508,15 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager",
|
||||
&socfpga_a10_fpga_mgr_ops, priv);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
mgr = fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager",
|
||||
&socfpga_a10_fpga_mgr_ops, priv);
|
||||
if (IS_ERR(mgr)) {
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return PTR_ERR(mgr);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, mgr);
|
||||
|
||||
ret = fpga_mgr_register(mgr);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -571,12 +571,9 @@ static int socfpga_fpga_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager",
|
||||
&socfpga_fpga_ops, priv);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
return devm_fpga_mgr_register(dev, mgr);
|
||||
mgr = devm_fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
|
||||
&socfpga_fpga_ops, priv);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
|
|
@ -419,23 +419,16 @@ static int s10_probe(struct platform_device *pdev)
|
|||
|
||||
init_completion(&priv->status_return_completion);
|
||||
|
||||
mgr = fpga_mgr_create(dev, "Stratix10 SOC FPGA Manager",
|
||||
&s10_ops, priv);
|
||||
if (!mgr) {
|
||||
dev_err(dev, "unable to create FPGA manager\n");
|
||||
ret = -ENOMEM;
|
||||
goto probe_err;
|
||||
}
|
||||
|
||||
ret = fpga_mgr_register(mgr);
|
||||
if (ret) {
|
||||
mgr = fpga_mgr_register(dev, "Stratix10 SOC FPGA Manager",
|
||||
&s10_ops, priv);
|
||||
if (IS_ERR(mgr)) {
|
||||
dev_err(dev, "unable to register FPGA manager\n");
|
||||
fpga_mgr_free(mgr);
|
||||
ret = PTR_ERR(mgr);
|
||||
goto probe_err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, mgr);
|
||||
return ret;
|
||||
return 0;
|
||||
|
||||
probe_err:
|
||||
stratix10_svc_free_channel(priv->chan);
|
||||
|
@ -448,7 +441,6 @@ static int s10_remove(struct platform_device *pdev)
|
|||
struct s10_priv *priv = mgr->priv;
|
||||
|
||||
fpga_mgr_unregister(mgr);
|
||||
fpga_mgr_free(mgr);
|
||||
stratix10_svc_free_channel(priv->chan);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -116,12 +116,9 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(priv->io_base))
|
||||
return PTR_ERR(priv->io_base);
|
||||
|
||||
mgr = devm_fpga_mgr_create(kdev, "TS-73xx FPGA Manager",
|
||||
&ts73xx_fpga_ops, priv);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
return devm_fpga_mgr_register(kdev, mgr);
|
||||
mgr = devm_fpga_mgr_register(kdev, "TS-73xx FPGA Manager",
|
||||
&ts73xx_fpga_ops, priv);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
|
||||
static struct platform_driver ts73xx_fpga_driver = {
|
||||
|
|
|
@ -54,12 +54,9 @@ static int versal_fpga_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, "Xilinx Versal FPGA Manager",
|
||||
&versal_fpga_ops, NULL);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
return devm_fpga_mgr_register(dev, mgr);
|
||||
mgr = devm_fpga_mgr_register(dev, "Xilinx Versal FPGA Manager",
|
||||
&versal_fpga_ops, NULL);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
|
||||
static const struct of_device_id versal_fpga_of_match[] = {
|
||||
|
|
|
@ -140,22 +140,17 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
|
|||
|
||||
clk_disable(priv->clk);
|
||||
|
||||
br = devm_fpga_bridge_create(&pdev->dev, priv->ipconfig->name,
|
||||
&xlnx_pr_decoupler_br_ops, priv);
|
||||
if (!br) {
|
||||
err = -ENOMEM;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, br);
|
||||
|
||||
err = fpga_bridge_register(br);
|
||||
if (err) {
|
||||
br = fpga_bridge_register(&pdev->dev, priv->ipconfig->name,
|
||||
&xlnx_pr_decoupler_br_ops, priv);
|
||||
if (IS_ERR(br)) {
|
||||
err = PTR_ERR(br);
|
||||
dev_err(&pdev->dev, "unable to register %s",
|
||||
priv->ipconfig->name);
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, br);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk:
|
||||
|
|
|
@ -247,13 +247,10 @@ static int xilinx_spi_probe(struct spi_device *spi)
|
|||
return dev_err_probe(&spi->dev, PTR_ERR(conf->done),
|
||||
"Failed to get DONE gpio\n");
|
||||
|
||||
mgr = devm_fpga_mgr_create(&spi->dev,
|
||||
"Xilinx Slave Serial FPGA Manager",
|
||||
&xilinx_spi_ops, conf);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
return devm_fpga_mgr_register(&spi->dev, mgr);
|
||||
mgr = devm_fpga_mgr_register(&spi->dev,
|
||||
"Xilinx Slave Serial FPGA Manager",
|
||||
&xilinx_spi_ops, conf);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
|
|
@ -609,20 +609,16 @@ static int zynq_fpga_probe(struct platform_device *pdev)
|
|||
|
||||
clk_disable(priv->clk);
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, "Xilinx Zynq FPGA Manager",
|
||||
&zynq_fpga_ops, priv);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, mgr);
|
||||
|
||||
err = fpga_mgr_register(mgr);
|
||||
if (err) {
|
||||
mgr = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
|
||||
&zynq_fpga_ops, priv);
|
||||
if (IS_ERR(mgr)) {
|
||||
dev_err(dev, "unable to register FPGA manager\n");
|
||||
clk_unprepare(priv->clk);
|
||||
return err;
|
||||
return PTR_ERR(mgr);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, mgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,12 +95,9 @@ static int zynqmp_fpga_probe(struct platform_device *pdev)
|
|||
|
||||
priv->dev = dev;
|
||||
|
||||
mgr = devm_fpga_mgr_create(dev, "Xilinx ZynqMP FPGA Manager",
|
||||
&zynqmp_fpga_ops, priv);
|
||||
if (!mgr)
|
||||
return -ENOMEM;
|
||||
|
||||
return devm_fpga_mgr_register(dev, mgr);
|
||||
mgr = devm_fpga_mgr_register(dev, "Xilinx ZynqMP FPGA Manager",
|
||||
&zynqmp_fpga_ops, priv);
|
||||
return PTR_ERR_OR_ZERO(mgr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
|
|
@ -22,6 +22,23 @@ struct fpga_bridge_ops {
|
|||
const struct attribute_group **groups;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fpga_bridge_info - collection of parameters an FPGA Bridge
|
||||
* @name: fpga bridge name
|
||||
* @br_ops: pointer to structure of fpga bridge ops
|
||||
* @priv: fpga bridge private data
|
||||
*
|
||||
* fpga_bridge_info contains parameters for the register function. These
|
||||
* are separated into an info structure because they some are optional
|
||||
* others could be added to in the future. The info structure facilitates
|
||||
* maintaining a stable API.
|
||||
*/
|
||||
struct fpga_bridge_info {
|
||||
const char *name;
|
||||
const struct fpga_bridge_ops *br_ops;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fpga_bridge - FPGA bridge structure
|
||||
* @name: name of low level FPGA bridge
|
||||
|
@ -62,15 +79,10 @@ int of_fpga_bridge_get_to_list(struct device_node *np,
|
|||
struct fpga_image_info *info,
|
||||
struct list_head *bridge_list);
|
||||
|
||||
struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
|
||||
const struct fpga_bridge_ops *br_ops,
|
||||
void *priv);
|
||||
void fpga_bridge_free(struct fpga_bridge *br);
|
||||
int fpga_bridge_register(struct fpga_bridge *br);
|
||||
struct fpga_bridge *
|
||||
fpga_bridge_register(struct device *parent, const char *name,
|
||||
const struct fpga_bridge_ops *br_ops,
|
||||
void *priv);
|
||||
void fpga_bridge_unregister(struct fpga_bridge *br);
|
||||
|
||||
struct fpga_bridge
|
||||
*devm_fpga_bridge_create(struct device *dev, const char *name,
|
||||
const struct fpga_bridge_ops *br_ops, void *priv);
|
||||
|
||||
#endif /* _LINUX_FPGA_BRIDGE_H */
|
||||
|
|
|
@ -105,6 +105,36 @@ struct fpga_image_info {
|
|||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fpga_compat_id - id for compatibility check
|
||||
*
|
||||
* @id_h: high 64bit of the compat_id
|
||||
* @id_l: low 64bit of the compat_id
|
||||
*/
|
||||
struct fpga_compat_id {
|
||||
u64 id_h;
|
||||
u64 id_l;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fpga_manager_info - collection of parameters for an FPGA Manager
|
||||
* @name: fpga manager name
|
||||
* @compat_id: FPGA manager id for compatibility check.
|
||||
* @mops: pointer to structure of fpga manager ops
|
||||
* @priv: fpga manager private data
|
||||
*
|
||||
* fpga_manager_info contains parameters for the register_full function.
|
||||
* These are separated into an info structure because they some are optional
|
||||
* others could be added to in the future. The info structure facilitates
|
||||
* maintaining a stable API.
|
||||
*/
|
||||
struct fpga_manager_info {
|
||||
const char *name;
|
||||
struct fpga_compat_id *compat_id;
|
||||
const struct fpga_manager_ops *mops;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fpga_manager_ops - ops for low level fpga manager drivers
|
||||
* @initial_header_size: Maximum number of bytes that should be passed into write_init
|
||||
|
@ -143,17 +173,6 @@ struct fpga_manager_ops {
|
|||
#define FPGA_MGR_STATUS_IP_PROTOCOL_ERR BIT(3)
|
||||
#define FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR BIT(4)
|
||||
|
||||
/**
|
||||
* struct fpga_compat_id - id for compatibility check
|
||||
*
|
||||
* @id_h: high 64bit of the compat_id
|
||||
* @id_l: low 64bit of the compat_id
|
||||
*/
|
||||
struct fpga_compat_id {
|
||||
u64 id_h;
|
||||
u64 id_l;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fpga_manager - fpga manager structure
|
||||
* @name: name of low level fpga manager
|
||||
|
@ -191,17 +210,18 @@ struct fpga_manager *fpga_mgr_get(struct device *dev);
|
|||
|
||||
void fpga_mgr_put(struct fpga_manager *mgr);
|
||||
|
||||
struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name,
|
||||
const struct fpga_manager_ops *mops,
|
||||
void *priv);
|
||||
void fpga_mgr_free(struct fpga_manager *mgr);
|
||||
int fpga_mgr_register(struct fpga_manager *mgr);
|
||||
struct fpga_manager *
|
||||
fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info);
|
||||
|
||||
struct fpga_manager *
|
||||
fpga_mgr_register(struct device *parent, const char *name,
|
||||
const struct fpga_manager_ops *mops, void *priv);
|
||||
void fpga_mgr_unregister(struct fpga_manager *mgr);
|
||||
|
||||
int devm_fpga_mgr_register(struct device *dev, struct fpga_manager *mgr);
|
||||
|
||||
struct fpga_manager *devm_fpga_mgr_create(struct device *dev, const char *name,
|
||||
const struct fpga_manager_ops *mops,
|
||||
void *priv);
|
||||
struct fpga_manager *
|
||||
devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info);
|
||||
struct fpga_manager *
|
||||
devm_fpga_mgr_register(struct device *parent, const char *name,
|
||||
const struct fpga_manager_ops *mops, void *priv);
|
||||
|
||||
#endif /*_LINUX_FPGA_MGR_H */
|
||||
|
|
|
@ -7,6 +7,27 @@
|
|||
#include <linux/fpga/fpga-mgr.h>
|
||||
#include <linux/fpga/fpga-bridge.h>
|
||||
|
||||
struct fpga_region;
|
||||
|
||||
/**
|
||||
* struct fpga_region_info - collection of parameters an FPGA Region
|
||||
* @mgr: fpga region manager
|
||||
* @compat_id: FPGA region id for compatibility check.
|
||||
* @priv: fpga region private data
|
||||
* @get_bridges: optional function to get bridges to a list
|
||||
*
|
||||
* fpga_region_info contains parameters for the register_full function.
|
||||
* These are separated into an info structure because they some are optional
|
||||
* others could be added to in the future. The info structure facilitates
|
||||
* maintaining a stable API.
|
||||
*/
|
||||
struct fpga_region_info {
|
||||
struct fpga_manager *mgr;
|
||||
struct fpga_compat_id *compat_id;
|
||||
void *priv;
|
||||
int (*get_bridges)(struct fpga_region *region);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fpga_region - FPGA Region structure
|
||||
* @dev: FPGA Region device
|
||||
|
@ -37,15 +58,12 @@ struct fpga_region *fpga_region_class_find(
|
|||
|
||||
int fpga_region_program_fpga(struct fpga_region *region);
|
||||
|
||||
struct fpga_region
|
||||
*fpga_region_create(struct device *dev, struct fpga_manager *mgr,
|
||||
int (*get_bridges)(struct fpga_region *));
|
||||
void fpga_region_free(struct fpga_region *region);
|
||||
int fpga_region_register(struct fpga_region *region);
|
||||
struct fpga_region *
|
||||
fpga_region_register_full(struct device *parent, const struct fpga_region_info *info);
|
||||
|
||||
struct fpga_region *
|
||||
fpga_region_register(struct device *parent, struct fpga_manager *mgr,
|
||||
int (*get_bridges)(struct fpga_region *));
|
||||
void fpga_region_unregister(struct fpga_region *region);
|
||||
|
||||
struct fpga_region
|
||||
*devm_fpga_region_create(struct device *dev, struct fpga_manager *mgr,
|
||||
int (*get_bridges)(struct fpga_region *));
|
||||
|
||||
#endif /* _FPGA_REGION_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче