forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
2.5 KiB
109 lines
2.5 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
/* |
|
* FPGA Bridge Driver for FPGA Management Engine (FME) |
|
* |
|
* Copyright (C) 2017-2018 Intel Corporation, Inc. |
|
* |
|
* Authors: |
|
* Wu Hao <[email protected]> |
|
* Joseph Grecco <[email protected]> |
|
* Enno Luebbers <[email protected]> |
|
* Tim Whisonant <[email protected]> |
|
* Ananda Ravuri <[email protected]> |
|
* Henry Mitchel <[email protected]> |
|
*/ |
|
|
|
#include <linux/module.h> |
|
#include <linux/fpga/fpga-bridge.h> |
|
|
|
#include "dfl.h" |
|
#include "dfl-fme-pr.h" |
|
|
|
struct fme_br_priv { |
|
struct dfl_fme_br_pdata *pdata; |
|
struct dfl_fpga_port_ops *port_ops; |
|
struct platform_device *port_pdev; |
|
}; |
|
|
|
static int fme_bridge_enable_set(struct fpga_bridge *bridge, bool enable) |
|
{ |
|
struct fme_br_priv *priv = bridge->priv; |
|
struct platform_device *port_pdev; |
|
struct dfl_fpga_port_ops *ops; |
|
|
|
if (!priv->port_pdev) { |
|
port_pdev = dfl_fpga_cdev_find_port(priv->pdata->cdev, |
|
&priv->pdata->port_id, |
|
dfl_fpga_check_port_id); |
|
if (!port_pdev) |
|
return -ENODEV; |
|
|
|
priv->port_pdev = port_pdev; |
|
} |
|
|
|
if (priv->port_pdev && !priv->port_ops) { |
|
ops = dfl_fpga_port_ops_get(priv->port_pdev); |
|
if (!ops || !ops->enable_set) |
|
return -ENOENT; |
|
|
|
priv->port_ops = ops; |
|
} |
|
|
|
return priv->port_ops->enable_set(priv->port_pdev, enable); |
|
} |
|
|
|
static const struct fpga_bridge_ops fme_bridge_ops = { |
|
.enable_set = fme_bridge_enable_set, |
|
}; |
|
|
|
static int fme_br_probe(struct platform_device *pdev) |
|
{ |
|
struct device *dev = &pdev->dev; |
|
struct fme_br_priv *priv; |
|
struct fpga_bridge *br; |
|
|
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
|
if (!priv) |
|
return -ENOMEM; |
|
|
|
priv->pdata = dev_get_platdata(dev); |
|
|
|
br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge", |
|
&fme_bridge_ops, priv); |
|
if (!br) |
|
return -ENOMEM; |
|
|
|
platform_set_drvdata(pdev, br); |
|
|
|
return fpga_bridge_register(br); |
|
} |
|
|
|
static int fme_br_remove(struct platform_device *pdev) |
|
{ |
|
struct fpga_bridge *br = platform_get_drvdata(pdev); |
|
struct fme_br_priv *priv = br->priv; |
|
|
|
fpga_bridge_unregister(br); |
|
|
|
if (priv->port_pdev) |
|
put_device(&priv->port_pdev->dev); |
|
if (priv->port_ops) |
|
dfl_fpga_port_ops_put(priv->port_ops); |
|
|
|
return 0; |
|
} |
|
|
|
static struct platform_driver fme_br_driver = { |
|
.driver = { |
|
.name = DFL_FPGA_FME_BRIDGE, |
|
}, |
|
.probe = fme_br_probe, |
|
.remove = fme_br_remove, |
|
}; |
|
|
|
module_platform_driver(fme_br_driver); |
|
|
|
MODULE_DESCRIPTION("FPGA Bridge for DFL FPGA Management Engine"); |
|
MODULE_AUTHOR("Intel Corporation"); |
|
MODULE_LICENSE("GPL v2"); |
|
MODULE_ALIAS("platform:dfl-fme-bridge");
|
|
|